数据库四大范式
一、 概念
在创建一个数据库的过程中,必须依照一定的准则,这些准则被称为范式,从第一到第六共六个范式。
二、 背景
数据库的规范化(上一篇博客有写到)的程度不同,便有了这么多种范式。数据库范式是数据库设计必不可少的知识,没有对范式的理解,就无法设计出高效率、优雅的数据库,甚至设计出错误误的数据库。
三、 目标
一般数据库设计只要遵循第一范式,第二范式,和第三范式就足够了,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。
使用正确的数据结构,不仅有助于对数据库进行相应的存取操作,还可以极大地简化应用程序中的其他内容(查询、窗体、报表、代码等),按照“数据库规范化”对表进行设计,其目的就是减少数据库中的数据冗余,以增加数据的一致性。
四、 概念
1、 候选键:唯一识别该表的属性或属性组。而其任何、子集都不能再标识,则称该属性组为(超级码)候选码。
例如:在学生实体中,“学号”是能唯一的区分学生实体的,同时又假设“姓名”、“班级”的属性组合足以区分学生实体,那么{学号}和{姓名,班级}都是(超级码)候选码。
2、 所谓依赖,就是函数依赖,就是映射。可以一对一,可以一对多,可以多对多。
五、 六大范式
第一范式(1NF):属性不可拆分 或 无重复的列
一个属性不允许再分成多个属性来建立列。事实上,在目前的DBMS中是不可能拆分属性的,因为他们不允许这么做。
如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。第一范式的模式要求属性值不可再分裂成更小部分,即属性项不能是属性组合或是由一组属性构成。
简而言之,第一范式就是无重复的列。例如,由“职工号”“姓名”“电话号码”组成的表(一个人可能有一部办公电话和一部移动电话),这时将其规范化为1NF可以将电话号码分为“办公电话”和“移动电话”两个属性,即职工(职工号,姓名,办公电话,移动电话)。
第二范式(2NF):(就是有一个唯一主键,并且非主属性对候选键是完全依赖。)(候选键可以是一个,也可以是两个,如果是关系表,一个候选键中一般有两个主属性,所以非主属性对候选键中的两个主属性的依赖,就要看是否是完全依赖。部分依赖会引起数据冗余。)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。
完全函数依赖
先讲讲什么是部分函数依赖。
部分函数依赖,就是多个属性决定另一个属性,但事实上,这多个属性是有冗余的。例如,(学号,班级)->姓名,事实上,只需要学号就能决定姓名,因此班级是冗余的,应该去掉。
如果关系模型R为第一范式,并且R中的每一个非主属性完全函数依赖于R的某个候选键,则称R为第二范式模式(如果A是关系模式R的候选键的一个属性,则称A是R的主属性,否则称A是R的非主属性)。
因此第二范式的目标就是消除函数依赖关系中左边存在的冗余属性。
例如,在选课关系表(学号,课程号,成绩,学分),关键字为组合关键字(学号,课程号),但由于非主属性学分仅依赖于课程号,对关键字(学号,课程号)只是部分依赖,而不是完全依赖,因此此种方式会导致数据冗余以及更新异常等问题,解决办法是将其分为两个关系模式:学生表(学号,课程号,分数)和课程表(课程号,学分),新关系通过学生表中的外关键字课程号联系,在需要时进行连接。
3.第三范式(3NF):消除传递依赖
满足第三范式的数据库必须先满足第二范式。
也就是,数据库中的非主属性仅能依赖于候选键,不存在与其他非主属性的关联。
例如,图书,图书室的关系。图书包括编号、出版商、页码等信息,图书室包括图书室编号、所存图书(外键)。其中,图书室的表中不应该存储任何图书的具体信息(例如,出版商。。),而只能通过主键图书编号来获得对应图书的信息。(这个例子只说明了不能部分依赖,跟传递依赖没啥关系,真是水啊)
以学生表(学号,姓名,课程号,成绩)为例,其中学生姓名无重名,所以该表有两个候选码(学号,课程号)和(姓名,课程号),故存在函数依赖:学号——>姓名,(学号,课程号)——>成绩,唯一的非主属性成绩对码不存在部分依赖,也不存在传递依赖,所以属性属于第三范式。
简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主属性信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。
总结一下:两个表相关联,一个表只能有另一个表的一个依赖。
一般系统设计需要符合第三范式。第三范式简而言之两个关联的表,一个表只能有另一个表的候选键,不能有共同的非主属性。
即,两个关联表,一个表A有另一个表B的非主属性c,表A有候选键a和b,b也是表B的候选键,此时的传递依赖关系为:A-B,B-c。此时不满足第三范式。
4.BC范式(BCNF):(候选键存在多个属性时,多个主属性直接要消除传递依赖关系)
(1)所有非主属性对每一个码都是完全函数依赖;
(2)所有的主属性对于每一个不包含它的码,也是完全函数依赖;
(3)没有任何属性完全函数依赖于非码的任意一个组合。
R属于3NF,不一定属于BCNF,如果R属于BCNF,一定属于3NF。
···
就是对于候选码中包含多个属性时,里面的关键字段互相没有依赖。
假设仓库管理关系表(仓库号,存储物品号,管理员号,数量),满足一个管理员只在一个仓库工作;一个仓库可以存储多种物品,则存在如下关系:
(仓库号,存储物品号)——>(管理员号,数量)
(管理员号,存储物品号)——>(仓库号,数量)
所以,(仓库号,存储物品号)和(管理员号,存储物品号)都是仓库管理关系表的候选码,表中唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库号)——>(管理员号)
(管理员号)——>(仓库号)
···
即存在关键字段决定关键字段的情况,因此其不符合BCNF。把仓库管理关系表分解为两个关系表仓库管理表(仓库号,管理员号)和仓库表(仓库号,存储物品号,数量),这样这个数据库表是符合BCNF的,并消除了删除异常、插入异常和更新异常。
5.第四范式(4NF):(一个表的主键只对应一个多值)
对于每一个X->Y,X都能找到一个候选码( 若关系中的某一属性组的值能唯一地表示一个元组,而其真子集不行,则称该属性组为候选码)。
设R是一个关系模型,D是R上的多值依赖集合。如果D中存在凡多值依赖X->Y时,X必是R的超键,那么称R是第四范式的模式。
例如,职工表(职工编号,职工孩子姓名,职工选修课程),在这个表中,同一个职工可能会有多个职工孩子姓名,同样,同一个职工也可能会有多个职工选修课程,即这里存在着多值事实,不符合第四范式。如果要符合第四范式,只需要将上表分为两个表,使它们只有一个多值事实,例如职工表一(职工编号,职工孩子姓名),职工表二(职工编号,职工选修课程),两个表都只有一个多值事实,所以符合第四范式。
6、总结:
第一范式、第二范式是对于本表内。第三范式、BC范式和第四范式涉及多表。
1、第一范式比较简单,属性不可拆分。电话号码一个字段可以分为手机号码和座机号码两个字段。
2、第二范式不难理解,非主属性对候选键完全依赖,不能存在部分依赖。候选键只有一个主属性时则一定符合第二范式。
候选键包含多个主属性时,可能出现不符合第二范式的情况,就是非主属性对多属性候选键部分函数依赖。在非主属性对多属性候选键完全函数依赖时,才符合第二范式。
3、第三范式去除冗余,非主属性只能存在一个表中,不应该存在多个表中,要去除无意义的数据冗余。
4、BC范式则不应存在关键字决定关键字的情况。也就是在关联关系表中,一个表有多个属性构成复合的候选键,主属性直接不应该有互相依赖。工号和身份证号是相互依赖。
5、第四范式,对于候选键只能存在不超过1个多值属性。要求把同一表内的多对多关系删除。
参考:https://blog.csdn.net/yahohi/article/details/7529710
https://blog.csdn.net/hyqsong/article/details/52245195
https://blog.csdn.net/dove_knowledge/article/details/71434960