设计关系数据库时,遵循不同的规范要求,设计出合理的关系型数据库,这些不同的范式要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以此类推,一般来说,数据库只需要满足第三范式(3NF)就可以了。
1.第一范式
所谓的第一范式(1NF)是指在关系模型中,对字段添加一个规范要求,所有的字段都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不是集合、数组、记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个字段值只能是实体的一个属性或一个属性的一部分。在任何一个关系数据库中,第一范式(1NF)是对关系模式设计的基本要求,一般设计中都必须满足第一范式(1NF)。只有这样,设计出来的表才是标准的二维表结构。
例如:如下的数据库表是符合第一范式的:
字段1 | 字段2 | 字段3 | 字段4 |
---|---|---|---|
而这样的数据库表是不符合第一范式的:
字段1 | 字段2 | 字段3 | 字段4 |
---|---|---|---|
字段3.1|字段3.2 |
很显然,在当前的任何关系数据库管理系统(DBMS)中,都不可能做出不符合第一范式的数据库,因为这些 DBMS 不允许把数据库表的一列再分成二列或者多列。因此,想在现有的 DBMS 中设计出不符合第一范式的数据库都是不可能的。
2.第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一的区分(标识)。选取一个能够区分每个实体的属性或属性组,作为实体的唯一标识,例如,在员工表中的身份证号码即可实现每个一员工的区分,该身份证号码即为候选键,任何一个候选键都可以被选作主键作为记录的唯一标识。在找不到候选键时,可额外增加属性以实现区分。例如,在员工表中如果没有对其身份证号码进行存储,而姓名可能会在数据库运行的某个时间重复,无法区分出实体时,这时就需要额外增加一个譬如 ID 等不重复的编号以实现区分,被添加的编号或 ID 选作主键。(该主键的添加是在 ER 设计时添加,不是建库时随意添加)。
第二范式(2NF)要求实体的属性要完全依赖于主关键字。所谓的完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一张新表,并且在新表中再增加原表中主键字段作为自己的外键,那么新表与原表之间就形成了一对多的关系。
总之,第二范式就是在第一范式的基础上非主属性(非主键字段)完全依赖于主属性(主键)。
例如:选课关系表为 SelectCourse(学号、姓名、年龄、课程名称、成绩、学分),主键为组合主键(学号、课程名称),因为存在如下决定关系:
(学号,课程名称)-> (姓名、年龄、成绩、学分)
在这个数据库表中,有某些依赖不满足第二范式的要求,因为存在着如下的决定:
(课程名称)-> (学分) 部分依赖主键
(学号) -> (姓名,年龄) 部分依赖主键
(学号、课程名称) -> (成绩) 完全依赖主键
由于不符合2NF,这个选课关系表会存在如下问题:
(1)数据冗余:
同一门课程由 n 个学生选修时,“学分” 就重复 n-1 次;
同一个学生选修了 m 门课程,姓名和年龄就重复了 m-1 /次;
(2)数据异常:
若调整了某门课程的学分,数据表中所有行的“学分”值都要更新,否则会出现同一门课程学分不同的情况。
(3)插入异常:
假设要开设一门新的课程,暂时没有人选修。这样,由于还没有“学号”关键字,课程名称和学分也无法记录入数据库。
(4)删除异常:
假设一批学生已经完成课程的选修,这些选修纪录就应该从数据表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这样也会导致插入异常。
解决方法:将部分依赖的属性和这个被部分依赖的主属性从原表中分离,形成一个新表。
上例的选课关系表应该拆分为 3张表,拆分后的表就可以满足第二范式的要求,从而彻底消除了前面列出的问题,它们分别是:
学生表:Student (学号,姓名,年龄)
课程表:Course (课程名称,学分)
选课关系表:SelectCourse (学号,课程名称,成绩)
另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字,就不会存在部分依赖。
3.第三范式
在1NF 基础上,任何非主属性不依赖于其它非主属性,即 3NF 就是在 2NF 基础上消除传递依赖,使得表中所有字段都直接依赖于主键字段。
第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。第三范式(3NF)要求一个关系表中不包含已在其它关系表已包含的非主键字段。例如,存在一个部门信息表,其中每个部门都有部门编号(dept_id)、部门名称,部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称,部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其他非主属性,也就是在满足 2NF 的基础上,任何非主属性不得传递依赖于与属性。
所谓传递函数依赖,指的是如果存在 “ A-> B -> C” 的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系:
关键字段 ->非关键字段x->非关键字段y
假设学生表为Student(学号、姓名、所在学院、学院地点、学院电话),关键字为单一关键字“学号”,因此存在如下决定关系:
(学号)->(姓名,年龄,所在学院,学院地点,学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
(学号)- >(所在学院)- >(学院地点,学院电话)