1
数据库技术及应用
1.5.2.3 2.2.3 关系型数据库设计原则
2.2.3 关系型数据库设计原则

在设计数据库时,通常需要使用E.F.Codd的关系规范化理论来指导关系型数据库的设计。E.F.Codd在1970年提出的关系数据库设计的三条规则,称为三范式(Normal Form),即第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以此类推。一般说来,数据库只需满足第三范式(3NF)即可。将这三个范式应用于关系型数据库的设计中,能够简化设计过程,并达到减小数据冗余、提高查询效率的目的。

2.2.3.1 第一范式(1NF)

所谓第一范式(1NF),是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)表中的每一行只包含一个实例的信息。简言之,第一范式就是无重复的列。

在表2-1所示的学生成绩表中出现了重复的属性,“课程1”和“课程2”是相同的字段,都是课程名,“成绩1”和“成绩2”也是相同的字段,应该把“课程1”和“课程2”合并成一个字段,“成绩1”和“成绩2”合并成一个字段,使其满足第一范式。

表2-1 学生成绩表

2.2.3.2 第二范式(2NF)

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即要满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。第二范式仅用于以两个或多个字段作为主关键字的场合,因为当字段作为表的关键字时,表中的所有字段必然完全依赖于这个主关键字,满足第二范式。

第二范式(2NF)要求实体的属性完全依赖于主关键字,要消除部分依赖。所谓完全依赖,是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分,通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式中的属性完全依赖于主键。

如学生信息系统,把所有这些信息放到一个表中(学号,学生姓名,年龄,性别,课程,课程学分,系别,系办地址,成绩),如表2-2所示。

表2-2 学生信息表

从表2-2中可以看出,存在如下的部分依赖关系:

(学号)→(姓名,年龄,性别,系别,系办地址);

(课程名称)→(学分);

(学号,课程)→(成绩);

因此,不能满足第二范式的要求,存在的问题主要有以下三点:

1.数据冗余

同一门课程有n个学生选修,“学分”就冗余地出现了n-1次;同一个学生选修了m门课程,姓名和年龄就冗余地出现了m-1次。

2.更新异常

(1)若调整了某门课程的学分,数据表中所有行的“学分”值都要更新,否则会出现同一门课程学分不同的情况。

(2)假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有“学号”关键字,课程名称和学分也无法记录入数据库。

3.删除异常

假设一批学生已经完成了课程的选修,则这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。这样就删除了不该删的信息,也就是导致了插入异常。

解决方法:把存在部分依赖的关键字和相应的属性分离出来作为一个新的实体,与原实体建立一对多的关系,根据以上的部分依赖分析,可以分解成如下的三个表:

学生表:Student(学号,学生姓名,年龄,性别,系别,系办地址),如表2-3所示。

课程表:Course(课程号,课程名称,学分),如表2-4所示。

选课关系:Select Course(学号,课程号,成绩),如表2-5所示。

表2-3 学生表(Student)

表2-4 课程表(Course)

表2-5 选课关系表(SelectCourse)

2.2.3.3 第三范式(3NF)

如果一个表满足第二范式,而且该表中的每一个非主关键字不传递依赖于主键,则称这个数据库表属于第三范式。

所谓传递依赖,是指数据库表中有A、B、C三个字段,如果字段B依赖于字段A,字段C又依赖于字段B,则称字段C传递依赖于字段A,并称该数据库表存在传递依赖关系。在一个数据库表中,如果有一个非主关键字完全依赖于另外一个非主关键字,则该字段必然传递依赖于主键。因而该数据库表就不满足第三范式。第三范式要求非主关键字之间没有从属关系。

在表2-3中的“学生”表中,“学号”是主关键字,字段“系办地址”依赖于“系别”,“系别”依赖于“学号”,所以“系办地址”传递依赖于“学号”,所以“学生”表不满足第三范式。要满足第三范式,需要把“学生”表分割为两个表,“学生”表和“系部”表两个表,将造成传递依赖的“系别”和“系办地址”放入“系部”表中,其他字段和“系别”放入“学生”表中。