一范式
一个关系模式应当是一个五元组:
R(U,D,DOM,F)
- 关系名为R
- U为一组属性
- D为属性组U中的属性所来自的域
- F为属性组U上的一组数据依赖
第一范式:每一个分量必须为不可分的数据项。
二范式
建立一个描述学校教务的数据库,该数据库涉及的对象包括学生的学号,所在系,系主任,课程名 和 成绩。该关系模型可表示为:
U = { 学号,姓名,系,系主任,课程名,分数 }
F = { 学号->姓名,学号->系,系->系主任,(学号,课名)-> 分数 }
但是这个关系模式存在以下问题:
- 数据冗余
每一个系的系主任姓名重复出现,重复次数与该系所有学生的所有课程成绩出现次数相同。 - 更新异常
由于数据冗余,当更新数据库中的数据时,系统要付出很大的代价来维护数据库的完整性,否则会面临数据不一致的危险,比如,某系更换系主任后,必须修改与该系学生有关的每一个元组。 - 插入异常
如果一个系刚成立,尚无学生,则无法把这个系及其系主任的信息存入数据库。 - 删除异常
如果某个系的学生全部毕业了,则在删除该系学生信息的同时,这个系以及系主任的信息也丢失掉了
因此可以得出一个结论,表1虽然满足第一范式,但它并不是一个好的模式,一个好的模式应当不会发生插入异常,删除异常和更新异常。
第二范式:2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。
-
函数依赖
数据依赖是一个关系内部属性与属性之间的一种约束关系,这种约束关系是通过属性间值得相等与否体现出来的数据间相关联系。其中最重要的是函数依赖和多值依赖。函数依赖普遍存在,比如描述一个学生的关系,可以有学号,姓名,系名等几个属性,由于一个学号只对应一个学生,一个学生只在一个系学习,所以,当学号确定后,学生的姓名及所在系的值也就被唯一确定,属性间的这种依赖关系类似于数学中的函数
y=f(x)
。在函数依赖中又有:-
完全函数依赖
在一张表中,若X -> Y,且对于X的任何一个真子集(加入属性组X包含超过一个属性的话),X -> Y不成立,那么我们称为Y对于X的完全函数依赖。
学号 -> 姓名
(学号,课名)-> 分数 -
部分函数依赖
假如Y函数依赖于X,但同时Y并不完全依赖于X,那么就称Y部分函数依赖于X。
(学号,课名)-> 姓名
传递函数依赖
假如 Z 函数依赖于 Y,且 Y 函数依赖于 X
-
码
设 K 为某表中的一个属性或属性组,若除 K 之外的所有属性都完全函数依赖于 K,那么我们称 K 为候选码,简称为码。
在实际中我们通常可以理解为:假如当 K 确定的情况下,该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码。一张表中可以有超过一个码。(实际应用中为了方便,通常选择其中的一个码作为主码)非主属性
包含在任何一个码中的属性就是主属性。除此之外,就是非主属性。
现在,在回来看2NF,表三是否符合2NF要求,根据2NF定义,判断的依据实际上就是看数据表中是否存在非主属性对于码的部分函数依赖。方法:
第一步:找出数据表中所有的码。
第二步:根据第一步所得到的码,找出所有的主属性。
第三步:数据表中,除去所有的主属性,剩下的就都是非主属性了。
第四步:查看是否存在非主属性对码的部分函数依赖。
1、表三的码只有一个,就是(学号,课名)。
2、主属性有两个:学号和课名
3、非主属性有四个:姓名,系名,系主任,分数
4、对于 (学号,课名)-> 姓名,有 学号 -> 姓名,存在非主属性 姓名 对 码(学号,课名)的部分函数依赖。
对于 (学号,课名)-> 系名,有 学号 -> 系名,存在非主属性 系名 对 码(学号,课名)的部分函数依赖
对于(学号,课名) -> 系主任,有 学号 -> 系主任,存在非主属性 对 码 (学号,课名)的部分函数依赖
所以,综上分析,该表只满足1NF,而不满足2NF的要求。为了消除部分函数依赖,只有一个办法,将大数据表拆分成两个或多个更小的数据表,这个过程叫做模式分解。模式分解并不唯一,以下是其中一种:
选课表(学号,课名,分数)
学生表(学号,姓名,系名,系主任)
- 数据冗余
每一个系的系主任姓名重复出现,重复次数与该系所有学生出现次数相同 - 有改进 - 更新异常
某系更换系主任后,必须修改与该系学生有关的每一个元组 - 无改进 - 插入异常
如果一个系刚成立,尚无学生,则无法把这个系及其系主任的信息存入数据库 - 无改进 - 删除异常
如果某个系的学生全部毕业了,则在删除该系学生信息的同时,这个系以及系主任的信息也丢失掉了 - 无改进
三范式
第三范式:3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖
对于选课表,主码为(学号,课名),主属性为学号和课名,非主属性只有一个,为分数。不可能存在传递函数依赖,所以选课表的设计,符合3NF的要求。
对于学生表,主码为(学号),主属性为学号,非主属性为姓名,系名和系主任。因为 学号 -> 系名,系名 -> 系主任,所以存在非主属性系主任对于码(学号)的传递函数依赖,所以学生表的设计,不符合3NF要求。
进一步模式分解:
选课(学号,课名,分数)
学生(学号,姓名,系名)
系(系名,系主任)
- 数据冗余
每一个系的系主任姓名重复出现,重复次数与该系所有学生出现次数相同 - 有改进 - 更新异常
某系更换系主任后,必须修改与该系学生有关的每一个元组 - 有改进 - 插入异常
如果一个系刚成立,尚无学生,则无法把这个系及其系主任的信息存入数据库 - 有改进 - 删除异常
如果某个系的学生全部毕业了,则在删除该系学生信息的同时,这个系以及系主任的信息也丢失掉了 - 有改进
因此可见,符合3NF要求的数据库设计,基本上解决了数据冗余,插入异常,修改异常,删除异常的问题。
BCNF范式
- 引例
- 某公司有若干个仓库。
- 每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作。
- 一个仓库中可以存放多种物品,一种物品也可以存放在不同的仓库中,每种物品在每个仓库中都有对应的数量。
那么关系模式 仓库(仓库名,管理员,物品名,数量)属于哪一级范式?
已知函数依赖集:
仓库名 -> 管理员,管理员 -> 仓库名,(仓库名,物品名)-> 数量
主属性:仓库名,管理员,物品名
非主属性:数量
因为:不存在非主属性对码的部分函数依赖和传递函数依赖。
所以:此关系模式属于3NF。
基于此关系模式的数据表,可能如图所示:
总结
- 1NF: 分量是最小的的单元不可再分 。
- 2NF:满足1NF,表中的字段必须完全依赖于全部主码而非部分主码 (一般我们都会做到)。
- 3NF:满足2NF,非主码外的所有字段必须互不依赖。
- 4NF:满足3NF,消除表中的多值依赖。
参考资料
1. https://www.zhihu.com/question/24696366
2. 王珊, 萨师煊. 数据库系统概论[M]. 北京:高等教育出版社,2014