1NF
1NF中的每个属性都不可再分,是所有关系型数据库的最基本要求。
即关系型数据库中不可能存在这样的表
在了解2NF之前首先要了解几个概念:
函数依赖
X→Y(X可能有多个属性),成Y函数依赖X
学号 → 姓名
(学号,课名) → 分数
完全函数依赖
X的任何一个真子集,都不能保证X→Y成立,称Y完全函数依赖X
例如:(学号,课名)→分数,但是X的真子集
学号→分数(一个学号多门课程)不成立
课名→分数(一门课程多个学生)不成立
部分函数依赖
Y依赖X,但不是完全依赖,即X的某一个属性也可以X→Y
(学号,课名) → 姓名,而 学号 →姓名 也成立
传递函数依赖
假如X→Y Y→Z 则称Z传递函数依赖于X
码
K 为某表中的一个属性或属性组,除K之外的所有属性都完全函数依赖于K,则K为码。(一个表中可能有多个码,选择一个即可)
例如:(学号、课名)这个属性组就是码
主属性和非主属性
主属性是码中的任何一个属性,除过主属性,表中的其他属性就是非主属性
例如:学号,课名都是主属性
2NF
满足1NF, 不存在非主属性对于码的部分函数依赖
例如
①找到数据表中的码:(学号、课名)
主属性:学号 课名 非主属性:姓名 分数 系名 系主任
②判断是否存在非主属性对于码的部分函数依赖
对于(学号,课名) → 姓名,有 学号 → 姓名,成立
对于(学号,课名) → 系名,有 学号 → 系名,成立
对于(学号,课名) → 系主任,有 学号 → 系主任,成立
为了让原表满足2NF,可以对原表进行细化,即把
原表:学号 姓名 课名 分数 系名 系主任
拆分成两个表
选课(学号,课名,分数)
学生(学号,姓名,系名,系主任)
分别判断
【选课表】
①找到数据表中的
码:(学号、课名) 主属性:学号和课名 非主属性:分数
②判断是否存在非主属性对于码的部分函数依赖
(学号,课名) → 分数,而学号→ 分数 课程→ 分数都不成立
【学生表】
①找到数据表中的
码:(学号) 主属性:学号 非主属性:姓名、系名、系主任
②判断是否存在非主属性对于码的部分函数依赖
学号→姓名,而姓名→学号 不成立
学号→系名,而系名→学号 不成立
学号→系主任,而系主任→学号 不成立
满足2NF
3NF
满足2NF,不存在非主属性对于码的传递函数依赖
【选课表】主码:(学号,课名) 主属性为学号和课名 非主属性:分数
不可能存在传递函数依赖,所以选课表的设计,符合3NF
【学生表】主码:学号 主属性:学号 非主属性:姓名、系名、系主任
因为 学号 → 系名,同时 系名 → 系主任,所以存在非主属性系主任对于码学号的传递函数依赖,所以学生表的设计,不符合3NF。
为了符合3NF要求,需要再一步对表进行细化,分解如下
选课(学号,课名,分数)
学生(学号,姓名,系名)
系(系名,系主任)
【选课表】符合3NF的要求,之前已经分析过了。
【学生表】主码:学号 主属性:学号 非主属性:系名、姓名
不可能存在非主属性对于码的传递函数依赖,所以符合3NF的要求。(姓名→系名不成立,因为同名不同系的存在)
【系表】主码:系名 主属性:系名 非主属性:系主任
不可能存在非主属性对于码的传递函数依赖(至少要有三个属性才可能存在传递函数依赖关系),所以符合3NF的要求。。
总结
范式 很少的冗余数据更新数据只需要修改更少的数据,在查询的时候需要更少的distinct或者group by语句。但是需要经常联合查询
反范式 因为所有的数据几乎都可以在一张表上显示,可以避免过多的联合查询,删除数据时候会造成表有些有用的信息丢失。所以要综合考虑使用范式和反范式。