一、1NF
1.1 1NF的定义:
关系数据库中的关系是要满足一定要求的,满足不同程度要求的为不同的范式。满足最低要求是第一范式(1NF),1NF的定义如下:
1NF:关系中的每一个分量必须是一个不可分的数据项。
通俗地说,第一范式就是表中不允许有小表的存在。比如,对于如下的员工表,就不属于第一范式:
员工表
员工编号 |
员工姓名 |
出生日期 |
薪资/月 |
所属部门 |
|
基本工资/月 |
补贴/月 |
||||
1 |
王红 |
19900908 |
9000 |
1000 |
101 |
... |
... |
... |
... |
... |
|
上表中,出现了属性薪资又被分为基本工资和补贴两个子属性,就好像表中有分割了一个小表,这就不属于第一范式。如果将基本工资和补贴合并,那么该表符合1NF。
1.2 1NF存在的问题:
1NF是最低一级的范式,范式程度不高,存在很多的问题。比如用一个单一的关系模式学生来描述学校的教务系统:
学生(学号,学生姓名,所在系,系主任姓名,课程号,成绩)
学生表
学号 |
学生姓名 |
所在系 |
系主任姓名 |
课程号 |
成绩 |
201102 |
张明 |
计算机系 |
章三 |
04 |
70 |
201103 |
王红 |
计算机系 |
章三 |
05 |
60 |
201103 |
王红 |
计算机系 |
章三 |
04 |
80 |
201103 |
王红 |
计算机系 |
章三 |
06 |
87 |
201104 |
李青 |
机械系 |
王五 |
09 |
79 |
... |
... |
... |
... |
... |
... |
这个表满足第一范式,但是存在如下问题:
·数据冗余:
一个系有很多的学生,同一个系的学生的系主任是相同的,所以系主任名会重复出现。
·更新复杂:
当一个系换了一个系主任后,对应的这个表必须修改与该系学生有关的每个元组。
·插入异常:
如果一个系刚成立,没有任何学生,那么这个无法把这个系的信息插入表中。
·删除异常:
如果一个系的学生都毕业了,那么在删除该系学生信息时,这个系的信息也丢了。
二、2NF
2.1 2NF的定义:
2NF:如果关系R属于1NF,且每一个非主属性完全函数依赖于任何一个候选码,则R属于2NF。
通俗地说,2NF就是在1NF的基础上,表中的每一个非主属性不会依赖复合主键中的某一个列。
按照定义,上面的学生表就不满足2NF,因为学号不能完全确定课程号和成绩(每个学生可以选多门课)。将学生表分解为:学生(学号,学生姓名,系编号),系(系编号,系名,系主任),选课(学号,课程号,成绩)。每张表均属于2NF。
2.2 2NF存在的问题:
下面举例说明2NF存在的相应问题。
对于公司里的员工管理,每个员工只能属于一个部门,每个部门可以有多个员工,定义如下关系模式:
员工管理表(员工id,员工名,所属部门id,部门经理);
对应的表:
员工管理表
员工号 |
员工名 |
所属部门 |
部门经理 |
001 |
小王 |
销售部 |
张三 |
002 |
小张 |
销售部 |
张三 |
003 |
小刘 |
研发部 |
李四 |
... |
... |
... |
... |
存在的问题:
1、删除异常:
如果某个部门的人都跳槽了,那么在删除这些员工的同时也丢失了这个部门的信息。
2、修改复杂:
如果一个员工换了一个部门,不但要修改所属部门,还要修改部门经理这个属性列。
3、插入异常:
如果公司新成立了一个部门,但是目前没有招收员工,那么这个部门信息也无法插入到这个表中,因为没有主键。
三、3NF
3.1 3NF的定义:
3NF的定义:在满足1NF的基础上,表中不存在非主属性对码的传递依赖。也就是说表中非主属性不会间接地依赖于码。
如上面的员工管理表就不属于3NF,因为非主属性部门经理依赖于所属部门,所属部门依赖于员工id,即部门经理传递依赖于员工id。将员工管理表分解:员工管理(员工id,员工名,部门名),部门(部门名,部门经理)。则每张表均属于3NF。
3.2 3NF存在的问题:
现在有这样的一个场景:对于一个工程(ENO)的实施,每个工程需要多个零件,每个供应商(SNO)只生产一个零件(PNO)且受工厂规模所限只能同时供应一个工程,每个工程使用的同一个零件都来自同一个生产商。
定义关系模式:SPE(SNO,PNO,ENO)。
SPE表
SNO |
PNO |
ENO |
上海齿轮加工厂 |
齿轮 |
造船工程 |
上海螺母加工厂 |
螺母 |
造船工程 |
鞍山钢床加工厂 |
钢床 |
造船工程 |
天津齿轮加工厂 |
齿轮 |
机车制造工程 |
天津螺母加工厂 |
螺母 |
机车制造工程 |
... |
... |
... |
上表中存在如下函数依赖:
(ENO,PNO)→SNO
(ENO,SNO)→PNO
SNO→PNO
SPE是属于3NF的,因为根据定义,表中不存在非主属性对码的传递依赖和部分依赖。但是这张表存在如下的问题:
1、插入异常:
如果有一个新的工厂建立了,但是这家工厂还没有接到任何订单,那么无法将这个工厂信息插入到SPE中,因为缺少了主属性ENO。
2、删除异常:
如果某个供应商只给一个工程提供零件,现在这个工程不再需要这个零件了。那么PNO就要删除,而PNO是主属性,整个元组都被删除了,这样就丢失了一个供应商信息。
四、BCNF
4.1 BCNF的定义:
BCNF比3NF更进一步,可以认为是扩充的3NF,其定义如下:
在第一范式的基础上,若关系R中的每一个决定因素都必含有码,则关系R属于BCNF。
很显然,上面的SPE表不属于BCNF,因为SPE中存在一个决定因素SNO,SNO不含有码。将SPE表分解:SP(SNO,PNO),SE(SNO,ENO)。则每张表均属于BCNF。
4.2 BCNF存在的问题:
仍以上面的工程实施场景为例:假设每个供应商可以生产多个零件,可以供应给多个工程,一个工程需要多个零件,但同一个工程的同一个零件必须来自同一个供应商。
那么关系SPE(SNO,PNO,ENO)对应的表数据可能是如下:
SPE表
SNO |
PNO |
ENO |
S1 |
P1 |
E1 |
S1 |
P1 |
E2 |
S1 |
P1 |
E3 |
S1 |
P2 |
E1 |
S1 |
P2 |
E2 |
S1 |
P2 |
E3 |
S2 |
P5 |
E4 |
S2 |
P5 |
E5 |
S2 |
P7 |
E4 |
... |
... |
... |
此时表SPE存在如下的函数依赖:
(PNO,ENO)→SNO
根据BCNF的定义,此时表SPE属于BCNF。但是这样的关系模式仍具有不好的地方:数据冗余度太大。假如供应商S3生产了n个零件,每个零件供应给m个工程,那么显然S3要在表中重复m*n次。
五、4NF
5.1 4NF的定义:
定义:关系模式R属于1NF,对于R中的每一个非平凡多值依赖X→→Y,X都含有码,则R属于4NF。
通俗地说,对于有三个属性的表,给定属性A一个值,剩余两个列之间不存在多对多的关系。例如,在上面的SPE表中,给定SNO=S1,PNO和ENO之间很明显存在多对多的关系,故上表是不属于4NF的。
根据4NF的定义可知,4NF所允许的非平凡的多值依赖实际上就是函数依赖,4NF就是消除表中的非平凡多值依赖关系。
5.2 4NF存在的问题:
一般地,4NF属于规范程度比较高的范式了。但是考虑到连接依赖的话,4NF中也仍存在数据冗余,插入、修改、删除异常等问题。如果消除了4NF中的连接依赖,则达到了5NF的关系模式。
六、对范式的学习总结:
如果只考虑函数依赖,那么BCNF范式最彻底,已消除插入和删除的异常。对比3NF,其不彻底性表现在表中可能存在主属性对码的部分依赖和传递依赖。
如果考虑到多值依赖,那么4NF范式是规范程度最高的。但4NF中可能存在连接依赖的关系,而5NF可以消除连接依赖。
在数据库中,有时并不是规范化程度越高越好。因为范式越高,产生的表就越多,一个简单的查询就可能涉及到多张表的关联。一般地,数据库中的表都在3NF。