模式设计理论主要包括三方面的内容:数据依赖、范式、模式设计方法。数据依赖研究数据之间的联系,起着核心的作用;范式是关系模式的标准;模式设计方法是自动化设计的基础。
关系模式的冗余指数据冗余。数据冗余 指同一个数据在系统中多次重复出现,这一直是影响系统性能的大问题。在文件系统中由于文件之间没有联系,一个数据会在多个文件中出现。数据库系统克服了文件系统的这种缺陷。
由于数据冗余,对数据操作时就会引起各种异常:修改异常、插入异常、删除异常。例如,关系模式 R(S#,C#,CNAME,TNAME)。一门课程有多名学生选修,CNAME,TNAME 就会重复出现多次,这就是数据冗余。修改一门课的名称或任课老师,就必须修改所有相关元祖,否则就会出现数据不一致。新增一门新课时,尚无学生选修,由于 S# 是主键,不能为空值,会造成插入异常。
“分解”是解决冗余的主要方法,也是规范化的一条原则:“关系模式有冗余问题,就分解它”。将上述关系模式分解为为 R1(S#,C#),R2(C#,CNAME,TNAME)两个关系模式,就解决了冗余问题,消除了操作异常。这样的分解是否最佳,也不是绝对的,如果要查学生的任课老师,就要对两个关系作连接操作,连接是有性能代价的。
在数据依赖中,函数依赖是最基本,最重要的一种依赖。
设有关系模式 R(A1,A2,…,An)或简记为 R(U),X,Y 是 U 的子集,r 是 R 的任一具体关系,如果对 r 的任意两个元组 t1 和 t2,由 t1[X] = t2[X] 导致 t1[Y] = t2[Y],则称 X 函数决定 Y,或 Y 函数依赖于 X,记为 X → Y。X → Y 为模式 R 的一个函数依赖。
这个定义可以这样理解:有一张设计好的二维表,X,Y 是表的某些列(可以是一列,也可以是多列),若在表中的第 t1 行,和第 t2 行上的 X 值相等,那么必有 t1 行和 t2 行的 Y 值也相等,这就是说 Y 函数依赖于 X,X 决定 Y。
例1,有一学生选课,教师任课数据的关系模式:R(S#,SNAME,AGE,SEX,C#,CNAME,SCORE,T#,TNAME,TITLE)。
根据常识,可以写出下列 FD 形式:S# → SNAME,C# → CNAME,(S#,C#) → SCORE,T# → (TNAME,TITLE)等。
例2,关系模式 R(ABCD),在 R 的关系中,属性值间有这样的联系:A 值与 B 值有一对多联系,C 值 与 D 值有一对一联系。试写出相应的函数依赖。
B → A,C ←→ D // 当 X → Y 和 Y → X 同时成立,可以写成 X ←→ Y
设 F 是关系模式 R 的一个函数依赖集,X,Y 是 R 的属性子集,如果从 F 中的函数依赖能够推出 X → Y,则称 F 逻辑蕴涵 X → Y,记为 F |= X → Y。
这个定义可以这样理解:一个关系模式可能有多个函数依赖形成函数依赖集,现在有一个新的函数依赖不在函数依赖集里,但如果能从集合里根据一定的规则推导出来,就说这个函数依赖集逻辑蕴涵这个新的函数依赖。比如,“根据身份证号能确定出生年月和性别”是已知的函数依赖,这就能推导出“根据身份证号能确定出生年月”,就说“根据身份证号能确定出生年月和性别”逻辑蕴涵“根据身份证号能确定出生年月”。
函数依赖的闭包 F+(加号是上标)是指被 F 逻辑蕴涵的函数依赖的全体构成的集合。
从已知的一些 FD 可以推导出另外一些 FD,这就需要一系列推理规则。FD 的推理规则最早出现在 1974 年 W.W.Armstrong 的论文里。
设有关系模式 R(U),X,Y,Z,W 均是 U 的子集,F 是 R 上只涉及到 U 中属性的函数依赖集,推理规则如下:(⊆ 读作包含于,⊇ 读作包含,开口方向的范围大)
例,设有关系模式 R,A、B、C、D、E、F 是它的属性集的子集,R 满足下列函数依赖: F = {A –> BC,CD –> EF},证明:函数依赖 AD –> F 成立。
证明:因为 A –> BC,所以 A –> C(分解性); AD –> CD(增广性);因为 CD –> EF,所以 AD - EF(传递性);AD –> F(传递性)成立。
当关系中属性集合 Y 是属性集合 X 的子集时(Y⊆X),若存在函数依赖 X → Y,即一组属性函数决定它的所有子集,这种函数依赖称为平凡函数依赖。
如 (Sno, Cno) → Sno ,(Sno, Cno) → Cno,平凡 FD 并没有什么实际意义。
当关系中属性集合 Y 不是属性集合 X 的子集时,存在函数依赖 X → Y,则称这种函数依赖为非平凡函数依赖。
例如,在关系 SC(Sno, Cno, Grade)中: (Sno, Cno) → Grade,Grade 不是 (Sno, Cno)的子集,但 (Sno, Cno)函数决定 Grade。
设关系模式 R 的属性集是 U,X 是 U 的一个子集。如果 X –> U 在 R 上成立,那么称 X 是 R 的一个超键(在关系中能唯一标识元组的属性集)。如果 X –> U 在 R 上成立,但对于 X 的任一真子集 X1 都有 X1 –> U 不成立,那么称 X 是 R 上的一个候选键(不含有多余属性的超键)。
例如,关系模式:R(S#,SNAME,AGE,SEX,C#,CNAME,SCORE,T#,TNAME,TITLE)。根据已知的 FD 和 推理规则,可以知道(S#,C#)能函数决定 R 的全部属性,并且是一个候选键。虽然(S#,SNAME,C#,CNAME)也能函数决定 R 的全部属性,但相比之下,只能说是一个超键,因为其中有多余属性。
说的白话一点,闭包就是由一个属性直接或间接推导出的所有属性的集合。
例如:设有函数依赖集 F= { A→D,AB→E,BI→E,CD→I,E→C },计算属性集 AE 关于 F 的闭包(AE)+。
解题:首先,A+ 包括自己,再找函数依赖于 A 的属性,都加入A+;E 也是如此。所以, A+ = { A },由 A –> D 得到 A+ = { A,D},由 E –> C,所以 E+ = { E,C },则 AE+ = { A,C,D,E},再由 CD –> I,最终 AE+ = { A,C,D,E,I }。
满足下列条件的函数依赖集 F 称为最小函数依赖集:
例1:设 F 是关系模式 R(ABC) 的 FD 集,F = {A –> BC,B –> C,A –> B,AB –> C},求其最小依赖集。
求 FD 的最小依赖集的算法:
对于存在数据冗余、插入异常、删除异常问题的关系模式,应采取分解为多个关系模式的方法进行处理,但这种分解过程必须是“可逆”的,即模式分解的结果应该能重新映像到分解前的关系模式。
模式分解就是将一个泛关系模式 R 分解成数据库模式 p,以 p 代替 R 的过程。它不仅仅是属性集合的分解,它是对关系模式上的函数依赖以及关系模式的当前值进行分解的具体表现。
下表将关系模式 R(ABC)分解成 p = {AB,AC},分解后的关系通过自然连接还原,未丢失信息,这种分解称为“无损分解”:
A |
B |
C |
|
A |
B |
|
A |
C |
1 |
1 |
1 |
|
1 |
1 |
|
1 |
1 |
1 |
2 |
1 |
|
1 |
2 |
|
下表将关系模式 R(ABC)分解成 p = {AB,AC},分解后的关系通过自然连接还原,会多出元组,丢失了信息,增加了噪声,并不是我们所期望的,这种分解称为“损失分解”:
A |
B |
C |
|
A |
B |
|
A |
C |
|
A |
B |
C |
1 |
1 |
4 |
|
1 |
1 |
|
1 |
4 |
|
1 |
1 |
4 |
1 |
2 |
3 |
|
1 |
2 |
|
1 |
3 |
|
1 |
1 |
3 |
|
|
|
|
|
|
|
|
|
|
1 |
2 |
4 |
|
|
|
|
|
|
|
|
|
|
1 |
2 |
3 |
最简单的理解,分解后的关系自然连接后完全等于分解前的关系,则这个分解相对于 F 是无损的连接分解。
举例:已知 R< U,F >,U = { A,B,C,D,E },F = { A → C,B → C,C → D,DE → C,CE → A },R 的一个分解为 R1(AD),R2(AB),R3(BE),R4(CDE),R5(AE),问这个分解是否具有无损连接性?
(1)建二维表,并对单元格值初始化
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b23 |
b24 |
b25 |
BE |
b31 |
a2 |
b33 |
b34 |
a5 |
CDE |
b41 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
b53 |
b54 |
a5 |
(2)因为 A → C,而 1,2,5 行 A 列的值均为 a1,C 列的值不同,修改为 b13。
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b13 |
b24 |
b25 |
BE |
b31 |
a2 |
b33 |
b34 |
a5 |
CDE |
b41 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
b13 |
b54 |
a5 |
(3)因为 B → C,修改之。
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b13 |
b24 |
b25 |
BE |
b31 |
a2 |
b13 |
b34 |
a5 |
CDE |
b41 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
b13 |
b54 |
a5 |
(4)因为 C → D,修改之。
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b13 |
a4 |
b25 |
BE |
b31 |
a2 |
b13 |
a4 |
a5 |
CDE |
b41 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
b13 |
a4 |
a5 |
(5)因为 DE → C,修改之。
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b13 |
a4 |
b25 |
BE |
b31 |
a2 |
a3 |
a4 |
a5 |
CDE |
b41 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
a3 |
a4 |
a5 |
(6)因为 CE → A,修改之。
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b13 |
a4 |
b25 |
BE |
a1 |
a2 |
a3 |
a4 |
a5 |
CDE |
a1 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
a3 |
a4 |
a5 |
(7)最终,BE 行形成了全 a,这个分解是无损分解。
|
A |
B |
C |
D |
E |
AD |
a1 |
b12 |
b13 |
a4 |
b15 |
AB |
a1 |
a2 |
b13 |
a4 |
b25 |
BE |
a1 |
a2 |
a3 |
a4 |
a5 |
CDE |
a1 |
b42 |
a3 |
a4 |
a5 |
AE |
a1 |
b52 |
a3 |
a4 |
a5 |
在分解过程中,要求模式分解的无损连接是必须的,只有无损连接分解才能保证任何一个关系能由它的那些投影进行自然连接得到恢复。同时,分解关系模式时还应保证关系模式的函数依赖集在分解后仍在数据库模式中保持不变,这就是保持函数依赖的问题。所有分解出的模式所满足的函数依赖的全体应当等价于原模式的函数依赖集。只有这样,才能确保整个数据库中数据的语义完整性不受破坏。
例1. 设有关系模式 R(WNO,WS,WG)的属性分别代表员工的工号、工资级别、工资数目。如果规定,每个职工只有一个工资级别,一个工资级别只有一个工资数目,那么 R 上的 FD 有 F = {WNO –> WS,WS –> WG},此时,按下表进行分解的话(p = {R1,R2},其中 R1 = {WNO –> WS},R2 = {WNO –> WG}):
WNO |
WS |
|
WNO |
WG |
|
WNO |
WS |
WG |
W1 |
8级 |
|
W1 |
2000 |
|
W1 |
8级 |
2000 |
W2 |
6级 |
|
W2 |
1600 |
|
W2 |
6级 |
1600 |
W3 |
6级 |
|
W3 |
1400 |
|
W3 |
6级 |
1400 |
可以验证,这个分解是无损分解。但从 R1,R2 这两个 FD 却推导不出 WS –> WG,因此分解 p 把 WS –> WG 丢失了,即 p 不保持函数依赖 F。一个无损分解不一定具有函数依赖保持性,反之,一个具有函数依赖保持性的分解也不一定是无损连接。
例2. 设关系模式 R(ABC),p = {AB,AC}是 R 的一个分解。试分析分别在 (1)F = {A –> B};(2)F = {A –> C,B –> C};(3)F = {B –> A};(4)F = {C –> B,B –> A}这四种情况下,p 是否具有无损分解和保持 FD 的分解特性?(注:使用上面介绍过的无损分解测试方法来验证就非常简单了)
解:
关系模式的好与坏,衡量的标准就是模式的范式(Normal Forms),简记为 NF。1NF 是基础,2NF 已成为历史,一般不再提及。数据库设计中最常用的是 3NF 和 BCNF。
关系模式 R 的每个关系 r 的属性值都是不可再分的原子值,那么称 R 是 第一范式。满足 1NF 的关系称为规范化的关系,关系数据库研究的都是规范化的关系,1NF 是关系模式应具备的最起码的条件。
如果关系模式 R 为第一范式,并且 R 中每一个非主属性完全函数依赖于 R 的某个候选键,则称为 第二范式。非主属性 指关系模式 R 中不包含在任何“键”中的属性。设有函数依赖 W –> A,若存在 X ⊆ W,有 X –> A 成立,那么称 W –> A 是局部依赖,否则就称 W –> A 是完全依赖。
例如,有关系模式 R(S#,C#,SCORE,T#,TITLE),(S#,C#)是 R 的候选键,R 上有两个 FD:(S#,C#)-> (T#,TITLE),C# -> (T#,TITLE),因此前一个是局部依赖,R 不是 2NF 模式。此时,R 的关系就会出现冗余和异常现象,如果一门课程有 100 个学生选修,关系中就会出现 100 个元组重复着 100 次的教师工号和职称。
如果关系模式 R 是第二范式,且每个非主属性都不传递依赖于 R 的候选键,则称为 第三范式。传递依赖:在关系模式中,如果 X –> Y,Y –> A,且 Y 不决定 X and A 不属于 Y,那么称 X –> A 是传递依赖。说白了,就是要求一个数据库的表中不包含已在其它表中包含的非主关键字信息。如上面提到的关系模式分解为 R1(S#,C#,SCORE)、R2(C#,T#)、R3(T#,TITLE),则符合 3NF。
3NF 的改进形式,消去主属性对键的传递函数依赖。
例. 设关系模式 R(ABCDE),R 的最小依赖集为 {A –> B,C –> D},从依赖集可知 R 的候选键为 ACE。根据最小依赖集,可知 p = {AB,CD},然后再加入由候选键组成的 ACE,因此,最终结果 p = {AB,CD,ACE}是一个 3NF 模式集且 p 相对于该依赖集是无损分解且保持 FD。
关系模式 R 相对于函数依赖集 F 分解成数据库模式 p = {R1,R2…,Rn},一般应具有以下特性:
设 U 是关系模式 R 的属性集,X 和 Y 是 U 的子集,Z = U - X - Y,小写的 xyz 表示属性集 XYZ 的值。对于 R 的关系 r,在 r 中存在元组(x,y1,z1)和(x,y2,z2)时,也存在元组(x,y2,z1)和(x,y1,z2)时,则称为多值依赖 (MVD)X –>-> Y 在模式 R 上成立。
关系模式 R(COURSE,STUDENT,PRECOURSE)表示课程、学生、这门课的前置课程。这个模式表达了两件事:一门课程有很多学生选修,一门课程有很多前置课程,都是 1:N 的联系,且两个联系是独立的。非形式的说,只要两个独立的 1:N 联系出现在一个关系中,就会出现多值依赖。模式 R 的属性值间一对多联系也可用 MVD 表示:COURSE –>-> STUDENT 和 COURSE –>-> PRECOURSE。
例. 设关系模式 R(A,B,C,D)在 R 上有如下五个相应的 FD 集及分解,回答下列问题,(1)确定 R 的关键码(2)是否无损分解?(3)是否保持 FD 集?(4)确定 p 中每一模式的范式级别。
提示1:求 R 的关键码或者候选键,应对所有子集,注意计算属性集的闭包,才能得到表示整个属性集的关键码或候选键!
提示2:是否无损分解需采用无损分解测试方法。
提示3:是否保持了函数依赖性,首先要分解 FD 集 F 的函数依赖,再根据分解模式去一一匹配。如 A –> CD 即 A –> C 和 A –> D。
提示4:关于范式,1NF 属性值达到了原子值;2NF 消除了次要属性对键的局部函数依赖;3NF 消除了次要属性对键的传递函数依赖;BCNF 消除了每一属性对键的传递函数依赖;4NF 消除了非平凡且非 FD 的 MVD
答:R 的关键码是 BD;p 不是无损分解;p 保持了 FD 集;p 中两个模式都达到 BCNF 级别。
答:R 的关键码有两个:AB 和 BC;p 是无损分解;p 没有保持 FD 集,丢失了 AB –> C;p 中两个模式都达到 BCNF 级别。
答:R 的关键码为 A 或 C;p 是无损分解;模式 ABC(F)={A –> BC,C –> A},模式 AD(F)={A –> D},所以 p 保持了 FD 集;模式 ABC 中的属性全是主属性,但有传递依赖(A –> BC,BC –> A),因此 ABC 是 3NF,但不是 BCNF,而模式 AD 是 BCNF 级别。
答:R 的关键码是 A;p 是无损分解;p 不保持了 FD 集,B –> C 丢失了;模式 AB 是 BCNF 级别,模式 ACD 只达到了 2NF 级别(D 依赖于 C 也依赖于 A,而 C 又依赖于 A,这里有冗余,3NF 不允许存在 关键码 –> 非主要属性1 –> 非主要属性2 )。
答:R 的关键码是 A;p 不是无损分解;p 不保持了 FD 集,B –> C 丢失了;p 中每个模式均为 BCNF 级别。