第六章 关系数据理论
6.1 问题的提出
本章主要讨论关系数据理论。在讨论数据库的时候,绕不开的一个问题是:针对一个具体问题,应该如何构建一个适合他的数据库模式。这是数据库设计的问题,确切地讲是关系数据库逻辑设计的问题。为了回答这个问题,人们提出了数据库逻辑设计的一个有力工具——关系数据库的规范化理论。
首先解释下主要符号:
通常使用R(U,D,DOM,F) 来表示一个关系模型,其中R是符号化的元组语义; U是一组属性; D是属性对应的域; DOM为属性到域的映射;F是属性组U上的一组数据依赖
再说说数据依赖的概念:
数据依赖是一个关系内部属性与属性之间的一种约束关系,这种约束关系通过属性间值相等与否来体现出数据之间的联系。它是现实世界属性间相互联系的抽象,是数据的内在性质。最重要的依赖类型是函数依赖和多值依赖。函数依赖广泛存在于生活中,比如描述一个学生的关系,可以有数个属性,但是有一个属性能够唯一标识学生(学号Sno),只要学号确定了,其他的属性也确定了,其关系类似于属性=f(学号)
作为一个二维表,关系要符合一个最基本的条件:每一个分量必须是不可分割的数据项。满足了这个条件的关系模式就属于第一范式(1NF)。也就是作为表中的数据,列是不可再分的,也就是不可以表中有表
假设仅仅建立一个Student表,其中对象包括学生的学号(Sno),所在系(Sdept),系主任名(Mname)、课程号(Cno)。那么学号Sno就是唯一标识属性,该表符合第一范式,但是有以下问题:
- 数据冗余:每一个系的系主任重复出现,浪费大量存储空间
- 更新异常:由于数据冗余,更新数据库信息的时候,系统需要很大代价来维护数据库完整性,比如更换一个系的系主任,就需要对该系的所有学生表项进行更改。
- 插入异常:如果一个系刚成立,还没有学生,就无法将这个系以及系主任加入数据库,这不符合常理。
- 删除异常:如果某个系的学生全部毕业了,那么在删除学生信息的时候会一并将系和系主任信息删除
因此可以知道,一个好的模式应该不发生插入、删除、更新异常,数据冗余应该尽量少
6.2 规范化
1.函数依赖
设R(U)是属性集合U上的关系模式,X和Y是U的子集,如果对于R中的任意一个可能的关系r,都不存在在两个元组在X上属性值相等,在Y属性值上不等,则称为X函数确定Y或者Y函数依赖于X。函数依赖和别的数据依赖一样是语义范畴的概念,只能根据予以来确定一个函数依赖。比如一个系只会有一个系主任,则不可能存在系别相同的情况下,系主任不同的情况,这样就可以说,根据系可以确定系主任,或者系主任依赖于系。换句话说,通过某一属性X的值可以确定属性Y的值,则称X函数确定Y或者Y函数依赖于X,记作 X → Y X\to Y X→Y。
下面是一些术语:
平凡函数依赖
如果
X
→
Y
X\to Y
X→Y而且Y是X的子集,那么称之为平凡函数依赖,比如在X=(学号,姓名),Y=姓名的时候,通过X是可以确定Y的,这就是平凡函数依赖
非平凡函数依赖
如果
X
→
Y
X\to Y
X→Y但Y不是X的子集,那么称之为非平凡函数依赖,比如X=学号,Y=性别的时候,通过X也是可以确定Y的,这就是非平凡依赖
完全函数依赖
如果
X
→
Y
X\to Y
X→Y,并且对于X的任何一个真子集X’,都有
X
′
↛
Y
X'\nrightarrow Y
X′↛Y,那么称之为完全函数依赖,比如X=班级号,Y=班级名,那么X的任一子集都没法完整地确定所有的班级名Y,这就是完全函数依赖
部分函数依赖
如果
X
→
Y
X\to Y
X→Y,并且对于X的某一个真子集X’,有
X
′
→
Y
X'\rightarrow Y
X′→Y,称之为非完全函数依赖,比如X=学号,Y=性别,那么只需要选择一男一女的学号,就可以完全确定性别Y的取值(男,女),那么这就是非完全函数依赖
2.码
码是关系模式中的一个重要概念,前面提到的码有候选码和主码。设K为关系R<U,K>的属性或者属性组合,如果U完全依赖于K,则K为R的候选码;如果U部分函数依赖于K,则K称为超码,虽然超码可以唯一标识一个实体,但是可能大多数超码中含有多余的属性。所以我们需要候选码。也就是比如学生实体中有{学号、姓名、性别、班级号}几个属性,那么{学号}可以是超码,{学号,姓名}也可以是,但是这些都有冗余信息在,因为实际上只需要学号就可以标识一个学生。
候选码是最小的超码,也就是K的任意一个真子集都不是候选码。如果候选码多于1个则选择其中一个作为主码。
包含在任何一个候选码中的属性称为主属性;不包含在任何候选码中的属性被称为非主属性或者非码属性。最极端的情况是,整个属性组都是码,这被称为全码
3.范式
关系数据库中的关系需要满足一定的要求,满足不同程度的要求的为不同范式。满足最低要求的叫做第一范式,前面已经介绍过了。在第一范式中满足进一步要求的称为第二范式,其余以此类推。
一个低一级的范式的关系模式可以通过模式分解转换为若干个高一级范式的关系模式的集合,这种过程叫做规范化。
假设有一个表SLC(Sno,Cno,Sdept,Sloc,Grade),其中Sno和Cno代表学生学号和所选的课,Sdept为系号,Sloc为为宿舍地址,每个系的学生都住在同一处,Grade为分数,并且Sno和Cno为主码,每一个系的学生都居住在同一栋宿舍楼。该表是符合1NF的,因为他每一列都是不可再分的。对范式的讲解中我们将会反复用到该例子。
4.第二范式2NF
如果R已经符合第一范式,而且每一个非主属性完全函数依赖于任何一个候选码,则R符合第二范式,这意味着二范式消除了非主属性对码的部分函数依赖。比如在表SLC(Sno,Cno,Sdept,Sloc,Grade)中,Sdept并不是完全依赖于候选码的,因为一个系有很多学生,Sno的子集也能决定Sdept,只需要在每个系中选出一个学生的数据就可以映射到所有系别,Sloc也是同理。2NF的主要思想是要尽量减少单个表中数据中的重复,并且要求尽可能将能够独立区分各个行的列作为候选码。
一个关系模式R不属于2NF,会产生以下几个问题:
- 插入异常:假如有学生尚未选课,则会因为课程号是主属性,导致无法插入数据
- 删除异常:假设学生(123,1,2,614,89)只选修了一门课,而且不打算选修课程1了,则会将整个元组都删除,会将整个学生都删除
- 数据冗余度大,修改复杂:如果一个学生选修了8门课,那么在该表中会有八条该生的信息,而且在这八条信息中都存储了相同的Sdept和Sloc值,浪费了存储空间。而且学生如果打算转系,也需要修改8条数据,修改耗时比较长。
解决方法:将他们分为两个表,一个是学生-宿舍表SL(Sno,Sdept,Sloc),另外一个是学生-课程表SC(Sno,Cno,Grade) ,这种办法称之为投影分解法
5.第三范式3NF
2NF消除了非主属性对码的部分函数依赖,但是仍然有不足。在SL(Sno,Sdept,Sloc)和SC(Sno,Cno,Grade) 中,Sloc传递函数依赖于Sno。这会有以下问题:
- 插入异常:如果有个系刚建立,尚未招生,那么我们无法将系信息录入数据库
- 删除异常:如果某个系学生全部毕业了,删除了所有的学生,那么该系的信息以及对应住址都会被删除掉。
- 修改复杂:如果某个系的学生需要搬到另外的宿舍,那么需要修改系中所有学生的信息。
3NF禁止了传递函数依赖,上述的SC表已经满足3NF了,但是SL表只满足2NF,解决办法是将SL分解为两个关系模式SD(Sno,Sdept)和DL(Sdept,Sloc),消除传递函数依赖
6.BCNF
BCNF比3NF又近了一步,通常认为BCNF是修正的第三范式。
BCNF规定,若关系模式R<U,F>中,如果每一个决定因素都包含码,则该关系模式符合BCNF。其中如果某一个属性组B依赖于属性组A(
A
→
B
A\to B
A→B),那么称属性组A为决定因素(听不懂没关系,下面有例子)
因此由定义可以得出结论:
- 所有非主属性对每一个码都是完全函数依赖
- 所有主属性对每一个不包含它的码也是完全函数依赖
- 没有任何属性完全依赖于非码属性的任何一组属性
假设有一个关系模式STJ(S,T,J),其中S为学生,T为教师,J为课程。假设一门课由多个老师来教授,每个老师只教一门课,某一学生选定了某门课就确定了一个固定的老师。那么该关系模式有三个函数依赖:T决定J,(S,J)决定T,(S,T)决定J。该关系模式有两个候选码(S,J)和(S,T),不存在非主属性对码的部分依赖和传递依赖,这个关系模式已经符合3NF了。但是存在依赖T决定J,因此T是决定因素,但是T并不包含码,因此STJ不符合BCNF。那么改进的方法是将STJ表拆分为TJ表和SJ表
关系模式SJP(S,J,P)中,S是学生,J是课程,P是名次,每一个学生旋球每一门课程有一定的名次,每一课程中每一个名次只有一个学生(也就是没有并列名次)。那么我们得到如下函数依赖:(S,J)决定P,(J,P)决定S,这个关系中陷入没有属性对码的传递依赖和部分依赖,因此符合3NF,而且除了(S,J)和(J,P)之外没有其他决定因素,也符合BCNF
4NF
在说第四范式之前首先要了解什么是多值依赖
我们举一个例子,关系模型Teaching(C,T,B)中C是课程,T是教师,B是参考书目。其结构如下:
该关系模式的码是(C,T,B),也就是全码,因此Teaching符合BCNF,但是当某一课程增加一名老师的时候,由于有多个参考书,因此需要插入多条信息。尽管上述关系已经符合BCNF,但是他的数据冗余依旧很明显,并且增删改都不方便,这是因为上述关系存在着多值依赖
定义
设R是属性及U上的一个关系模式,X,Y,Z都是U的子集,并且Z=U-X-Y,那么关系模式中多值依赖
X
→
→
Y
X\to\to Y
X→→Y成立,也就是当且仅当对R(U)的任一关系r,给定一对(x,z)的值,有一组Y的值,这组值仅仅决定于x的值但是和z值无关
多值依赖具有以下性质:
- 多值依赖具有对称性
- 多值依赖具有传递性
- 函数依赖可以看作是多值依赖的特殊情况
多值依赖和函数依赖相比,具有两个基本区别:
- 多值依赖的有效性和属性集合的范围有关
- 如果函数依赖(X决定Y)在R(U)上成立,则对于任何Y自己都有(X决定Y)成立。而多值依赖就不能有这种结论。
4NF是限制关系模式属性之间不允许有非平凡并且非函数依赖得多值以来。因为根据定义,对于每一个非平凡多值依赖 X → → Y X\to\to Y X→→Y,X都含有候选码,因此4NF所允许的非平凡多值依赖实际上就是函数依赖。显然,如果一个关系是4NF,则必为BCNF。