数据库三范式

一些专业名词

候选码:可唯一标识某一元组的属性组,属性组中各个属性缺一不可。【t_student】(学号,姓名,学院),姓名可能会重复,所以其中学号可以唯一标识一条记录,学号就是t_student的候选码。那么假设姓名不会重复,那么候选码就有学号和姓名两个。 又比如【t_grade】(学号,课程,成绩),其中一个学生可以有多条成绩记录,所以需要学号和课程号组合才可以唯一标识一条数据库记录,所以学号、课程号就是t_student的一个候选码。

主属性:候选码中的属性称为主属性。【t_student】(学号,姓名,学院),学号就是主属性

非主属性:不是主属性就是非主属性呗。【t_student】(学号,姓名,学院),姓名、学院就是非主属性

函数依赖

函数依赖的意义与函数类似,自变量经过映射得出因变量,比如(学号)可以确定(姓名),(课程号)可以确定(老师),(学号,课程号)可以确定(成绩)。假设属性组X能够唯一标识属性组Y,读作“Y函数依赖于X”,或者“X确定Y”,记作X--->Y。函数依赖主要分为完全函数依赖,部分函数依赖,传递函数依赖。

完全(Full)函数依赖:假设X--->Y,且X的任意真子集都不和Y有函数依赖关系,就称Y完全函数依赖于X。比如(学号,课程号)--->(成绩),学号和课程号就是X,成绩就是Y,少了学号、课程中的哪个属性都无法确定成绩,所以他们之间是完全函数依赖。表示方法如图。

部分(Part)函数依赖:相对于完全函数依赖,假设X--->Y,且X的某个真子集和Y也有函数依赖关系,就称Y部分函数依赖于X。比如(学号,姓名)--->(学院),这个函数依赖关系显然成立,另外(学号)--->(学院)这个函数依赖关系也成立,(学号)又是(学号,姓名)的真子集,所以(学院)部分函数依赖于(学号,姓名)。表示方法如图。

传递(Tranmission)函数依赖:当X--->Y,Y--->Z,且Y无法确定X时,就称Z传递函数依赖于X。比如(学号)--->(学院),(学院)--->(院负责人),我们可以得出(学号)--->(院负责人),这时院负责人传递函数依赖于学号。表示方法如图。

范式

什么是数据库范式?数据库范式就相当于数据库的设计等级,好比家电的环保等级,汽车的排量等级等,常说的数据库符合第二范式、第三范式也是这么个意思。下面介绍最常用的三个范式。

1NF

要求表中的每一个属性都不可再分,比如学生(学号,姓名,籍贯),籍贯可以在分为省份、市区,所以违反了第一范式。当然,是否违反第一范式要根据当前的项目环境来确定,如果认为籍贯就是一个字符串值,那也就没有违反第一范式。

2NF:每一个非主属性不部分函数依赖于候选码

当表的每一个非主属性都完全函数依赖于候选码,也就是说消除了非主属性与候选码之间的部分函数依赖,我们就说这个表满足第二范式,举个栗子。现有一张表,学生(学号,课程号,成绩,院系,院负责人),每个院系都有一名院负责人,(学号,课程号)确定成绩。很明显,候选码就是(学号,课程号),主属性也就是(学号,课程号),非主属性就是(成绩,院系,院负责人)。他们之间的函数依赖关系如图所示。

图中的黑色箭头描述的是函数依赖,而且都是完全函数依赖。但是,并没有把所以函数依赖关系都画出,我们知道,学号可以确定院系,即完全函数依赖(学号)--->(院系),而候选码(学号、课程号)也可以确定院系,即部分函数依赖(学号,课程号)--->(院系)。同理部分函数依赖(学号,课程号)--->(院负责人)也成立。补上两个函数依赖后如图。

图中的蓝色箭头描述的就是非主属性与候选码的部分函数依赖关系。既然发现了非主属性与候选码之间的部分函数依赖,就说明这个表不符合第二范式。那如果不符合第二范式,会造成什么问题呢?
数据冗余:假设软件学院有2000名学生,院负责人这个属性就要在数据库中重复2000次。

插入异常:如果学生还没有选课,课程号就为空,根据实体完整性,我们就无法将这条数据插入数据库中。

删除异常:如果某个学生仅选了一门课,现在他连这门课都不选了,删除这条记录,这样其相关的所有信息(院系、院负责人)也就都删掉了。

更新复杂:同样假设软件学院有2000名学生,现在换了院负责人,就要更新2000条数据库记录。

怎么将其范式化程度提高?常用的手段就是拆表,将其拆成“选课”、“学生”两张表,选课(学号,课程号,成绩),它的候选码是(学号,课程号);学生(学号,学院,院负责人)它的候选码是(学号)。他们的函数依赖关系如图所示。

可以看出,图中非主属性与候选码之间没有部分函数依赖关系,所以符合2NF。

3NF:每一个非主属性不传递函数依赖于候选码

第三范式要求非主属性与候选码之间没有传递函数依赖关系。拿上面的栗子来说,学生(学号,院系,院负责人),他们之间的函数依赖关系如图所示。

学号确定院负责人,这是一个完全函数依赖。但是,又有学号确定院系,院系确定院负责人,所以学号和院负责人之间也存在一个传递函数依赖关系:非主属性院负责人传递函数依赖于候选码学号。所以这个表不符合第三范式。那如果不符合第三范式,会造成什么问题呢?

数据冗余:假设软件学院有2000名学生,院负责人这个属性就要在数据库中重复2000次。

插入异常:好像木有...

删除异常:假设软件学院仅剩最后一名学生了,悲剧是他也毕业了,这条记录就要被删除,然后这个软件学院的信息也就没有了

更新负责:假设软件学院有2000名学生,院负责人这个属性就要在数据库中重复2000次。

同样,通过拆表,提高其范式化程度。拆成“学院”、“学生”两张表,学院(院系,负责人),学生(学号,院系)。他们的函数依赖关系如图所示。

可以看出,图中非主属性与候选码之间没有传递函数依赖关系,所以符合3NF。

讨论

范式化程度低造成的问题一般有哪些?
数据冗余、插入异常、删除异常、更新异常

提高范式化程度的手段是什么?
模式分解,俗称拆表

范式化程度越高越好吗?
并不是,就好比家电的环保等级,等级越高价格越贵。同样范式化程度越高,表也就越多,查询数据、插入数据就会越麻烦,所以一般情况下,数据库设计满足三范式即可,甚至有时做出反范式化的优化设计

引用

1.《数据系统概论》

posted @ 2017-05-15 17:52  付大石  阅读(1049)  评论(0编辑  收藏  举报