- 回顾(W9 第4章)
- 系统需求分析
- 功能需求分析
- 数据需求分析
- 业务规则及完整性约束分析
- 数据库概念设计
- 确定基本实体集及属性
- 主要业务局部概念建模
- 定义联系集及属性
- 局部ER图→整体ER图
- E-R模型转化方法
- 实体集转化方法
- 联系集转化方法
- 属性转化方法
- 类层次转化方法
- 聚合转化方法
- 系统需求分析
5.1 问题提出
- 本章要解决的两个问题
- 如何判断一个数据库模式是“好”的模式
- 如何设计出一个“好”模式?
数据冗余导致的问题
- 数据冗余是指同一信息在数据库中存储了多个副本。它可能引起下列问题:
- 冗余存储:信息被重复存储,导致浪费大量存储空间。
- 更新异常:当重复信息的一个副本被修改,所有副本都必须进行同样的修改。因此当更新数据时,系统要付出很大的代价来维护数据库的完整性,否则会面临数据不一致的危险。
- 插入异常:只有当一些信息事先已经存放在数据库中时,另外一些信息才能存入数据库中。
- 删除异常:删除某些信息时可能丢失其它信息。
数据冗余关系举例
- [例5.1] 考虑学生选课关系模式:
SCE(studentNo, studentName, courseNo, courseName, score),
属性集{studentNo, courseNo}是唯一候选码,也是主码。 - 如果允许一个学生选修多门课程,且一门课程可被多个学生选修,则该关系实例可能出现:
- 冗余存储:学生姓名和课程名被重复存储多次;
- 更新异常:当修改某学生的姓名或某课程的课程名时,可能只修改了部分副本的信息,而其他副本未被修改到;
- 插入异常:如果某学生没有选修课程,或某课程未被任何学生选修时,则该学生或该课程信息不能存入数据库,因为主码值不能为空;
- 删除异常:当某学生的所有选修课程信息都被删除时,则该学生的信息将被丢失。对课程也是如此。
数据冗余产生原因及解决方法
- SCE产生问题的原因:部分函数依赖
- 该模式中某些属性之间存在如下函数依赖关系
- studentNo→studentName(即学号决定姓名)
- courseNo→courseName(即课程编号决定课程名称)
- {studentNo, courseNo}→score
- 即studentName、courseName部分依赖于关系的主码。
- 该模式中某些属性之间存在如下函数依赖关系
- 解决方法:关系模式分解
- 分解为三个关系模式
- S(studentNo, studentName)
- C(courseNo, courseName)
- E (studentNo, courseNo, score)
- 分解为三个关系模式
模式分解导致的问题
- 将一个关系模式分解为较小关系模式集可解决冗余问题。但由此可能产生两个新的问题:
- 什么样的关系模式需要进一步分解为较小的关系模式集?
- 根据范式要求决定(后面讨论)
- 是否所有的模式分解都是有益的?
- 实例
- 什么样的关系模式需要进一步分解为较小的关系模式集?
模式分解问题举例
- [例5.2] 设一关系模式
STU (studentNo, studentName, sex, birthday, native, classNo),
其中,studentNo为主码。 - 假设将STU分解为以下两个子模式:
- STU1 (studentNo, studentName)
- STU2 (studentName, sex, birthday, native, classNo)
- 分解后会发生什么问题?
模式分解存在的问题
- 有损分解:两个分解后的关系通过连接运算还原得到的信息与原来关系的信息不一致。
- 如果能够通过连接分解后所得到的较小关系完全还原被分解关系的所有实例,称之为无损分解(lossless decomposition),也称该分解具有无损连接特性。
- 丢失依赖关系
- sex、birthday、age、native、classNo等与属性studentNo依赖关系也就不再存在。
- 如果被分解关系模式上的所有依赖关系都在分解得到的关系模式上保留,称该分解为依赖保持 (dependency preserving)分解。
小 结
- 一个 “好”的关系模式应该是:
- 数据冗余尽可能少(即数据共享尽可能高)
- 不发生插入异常、删除异常、更新异常等问题。
- 模式分解时,分解后的模式应具有无损连接、保持依赖等特性。
5.2 函数依赖定义
- 函数依赖(functional dependency, 简称FD)是一种完整性约束, 是现实世界事物属性之间的一种制约关系,它广泛地存在于现实世界之中。
- 定义5.1 设r( R )为关系模式,α⊆R,β⊆R。对任意合法关系r及其中任两个元组ti和tj,i≠j,若ti[α]=tj[α],则ti[β]=tj[β],则称α函数确定β , 或 β 函数依赖于α,记作α→β。
- 例如,对于第1个和第2个元组:t1[A,B]=t2[A,B]=(a1,b1),且t1[C]=t2[C]=c1。
- 例如,对于第1个和第2个元组:t1[A,B]=t2[A,B]=(a1,b1),且t1[C]=t2[C]=c1。
- 如果在图中再增加一个元组(a1, b1, c2, d1),那么函数依赖AB→C 还成立吗?不成立
函数依赖说明
- 对于函数依赖,需做如下说明:
- 函数依赖不是指关系模式r( R )的某个或某些关系实例满足的约束条件,而是指关系模式r( R )的所有关系实例均要满足的约束条件。
- 函数依赖是语义范畴的概念,只能根据数据的语义来确定函数依赖,是不能够被证明的。
- 数据库设计者可以对现实世界作强制的规定。
- 码约束是函数依赖的一个特例。码属性(集)相当于定义5.1中的α,关系中的所有属性相当于定义5.1中的β。
平凡与非平凡函数依赖
- 定义5.2 在关系模式r( R )中,α⊆R,β⊆R。若α→β,但β⊈α,则称α→β是非平凡函数依赖。否则,若β⊆α, 则称α→β是平凡函数依赖。
- 对于任一关系模式,平凡函数依赖都是必然成立的,它不反映新的语义。
完全函数依赖和部分函数依赖
- 定义5.3 在关系模式r( R )中,α⊆R,β⊆R,且α→β是非平凡函数依赖。若对任意的γ⊂α,γ→β都不成立,则称α→β 是完全函数依赖,简称完全依赖。否则,若存在非空的γ⊂α,使γ→β 成立,则称α→β是部分函数依赖,简称部分依赖。
- 如果α→β 是完全函数依赖, 且α≠β ,则α→β 一定是非平凡函数依赖。
- 如果α→β 是完全函数依赖, 且α≠β ,则α→β 一定是非平凡函数依赖。
完全函数依赖和部分函数依赖举例
- 当α是单属性时,则α→β完全函数依赖总是成立的。
- 例如,在关系SCE中
- 完全依赖:
- studentNo → studentName
- courseNo → courseName
- {studentNo, courseNo} → score
- 部分依赖:
- {studentNo, courseNo} → studentName
- {studentNo, courseNo} → courseName
- 完全依赖:
- 对候选码的部分函数依赖会导致数据冗余和插入、删除、更新异常!
传递函数依赖
- 定义5.4 在关系模式r( R )中,设α⊆R,β⊆R,γ⊆R,若α→β,β→γ,则必存在函数依赖α→γ;若α→β 、β→γ和α→γ都是非平凡函数依赖,且β↛ α,则称α→γ是传递函数依赖,简称传递依赖。
- 注意条件:β⊈α ,γ⊈β ,γ⊈α 和 β→/α。 为什么?
- 【注意】如果β→α,即α←→β,/ β⊈α / γ⊈β / γ⊈α,则γ直接依赖于α,而不是传递函数依赖。
- 由于β→/α ,因此 β 一定不是候选码。
- 注意条件:β⊈α ,γ⊈β ,γ⊈α 和 β→/α。 为什么?
- 传递依赖也可能会导致数据冗余及产生各种异常。
传递函数依赖举例
- [例5.4] 在关系模式SCI(studentNo, classNo, className, institute)中,存在下列函数依赖:
- studentNo → classNo
- classNo → className
- classNo → institute
- 因此,关系模式SCI中存在下列传递函数依赖:
- studentNo → className
- studentNo → institute
- SCI中存在传递依赖,因此可能导致数据冗余、更新异常、插入异常及删除异常。
- 请自己分析SCI中存在的各种异常问题。
函数依赖小结
- 函数依赖是指关系模式中属性之间存在的一种约束关系。这种约束关系既可以是现实世界事物或联系的属性之间客观存在的约束,也可以是数据库设计者根据应用需求或设计需要强加给数据的一种约束。
- 但不论是那种约束,一旦确定,进入数据库中的所有数据都必须严格遵守。
- 正确了解数据的意义及确定属性之间的函数依赖关系,对设计一个好的关系模式是十分重要的。
5.3 范式
范式概述
- 基于函数依赖理论,关系模式可分成
- 第一范式(1NF)
- 第二范式(2NF)
- 第三范式(3NF)
- Boyce-Codd范式(BCNF)
- 这几种范式的要求一个比一个严格,它们之间的联系为:
BCNF ⊂ 3NF ⊂ 2NF ⊂ 1NF - 满足BCNF范式的关系一定满足3NF范式,满足3NF范式的关系一定满足2NF范式,满足2NF范式的关系一定满足1NF范式。
第一范式(1NF) ——码
- 定义5.5 如果一关系模式r( R )的每个属性对应的域值都是不可分的(即原子的),则称r( R )属于第一范式,记为r( R )∈1NF.
- 第一范式的目标是:将基本数据划分成称为实体集或表的逻辑单元,当设计好每个实体后,需要为其指定主码。
第二范式(2NF) ——全部是码
- 定义5.6 设有一关系模式r( R ),α⊆R。若α包含在r( R )的某个候选码中,则称α为主属性,否则α为非主属性。
- 在SCE关系中,属性集{studentNo, courseNo}是SCE的唯一候选码。因此,属性studentNo和courseNo为主属性,其余属性为非主属性。
- 定义5.7: 如果一个关系模式r( R )∈1NF,且所有非主属性都完全函数依赖于r( R )的候选码,则称r( R )属于第二范式,记为r( R )∈2NF。
- SCE中存在依赖关系studentNo→studentName和courseNo→ courseName,即非主属性studentName和courseName部分依赖于SCE的候选码{studentNo, courseNo},故SCE∉2NF。
- 第二范式的目标:将只部分依赖于候选码(即依赖于候选码的部分属性)的非主属性移到其他表中。
- 也就是说,在满足第一范式的实体中,如果有复合候选码(即多个属性共同构成的候选码),那么所有非主属性必须依赖于全部的候选码,不允许依赖于部分的候选码属性。
- 即不允许候选码的一部分对非主属性起决定作用:全部是码
- 违背2NF的模式,即存在非主属性对候选码的部分依赖,则可能导致例5.1所述的数据冗余及异常问题。
- 对于非2NF范式的关系模式,可通过分解进行规范化,以消除部分依赖。
- 如将关系模式SCE分解为关系模式S、C和E。这样在每个关系模式中,所有非主属性对候选码都是完全函数依赖,因此都属于2NF范式。
- 2NF范式虽然消除了由于非主属性对候选码的部分依赖所引起的冗余及各种异常,但并没有排除传递依赖。因此,还需要对其进一步规范化。
第三范式(3NF) ——仅仅是码——定义1
- 第三范式的目标:去掉表中不直接依赖于候选码的非主属性.
- 定义5.8 如果一个关系模式r( R )∈2NF,且所有非主属性都直接函数依赖于r( R )的候选码(即不存在非主属性传递依赖于候选码),则称r( R )属于第三范式,记为r( R )∈3NF.
- 也就是说,在满足2NF的实体中,非主属性不能依赖于另一个非主属性(即非主属性只能直接依赖于候选码)
- 总之,所有的非主属性应该直接依赖于(即不能存在传递依赖,这是3NF的要求)全部的候选码(即必须完全依赖, 不能存在部分依赖,这是2NF的要求)。
范式举例
- [例5.5] r( R )=r(A, B, C, D),函数依赖集 F={AB→C, B→D}。r( R )的候选码为AB,r( R ) ∉2NF。
- 因为函数依赖B→D中的决定属性B只是候选码的一部分,即D部分依赖于候选码AB。
- 可将r( R )分解为r1(R1)=r1(A, B, C)、r2(R2)=r2(B, D)。 r1(R1)的候选码为AB,r2(R2)的候选码为B。
- 分解得到的r1(R1)和r2(R2)都属于3NF范式。
- [例5.6] r( R )=r(A, B, C),函数依赖集F={A→B, B→C}。r( R )的候选码为A,r( R )∈2NF,但 r( R )∉3NF。
- 因为函数依赖B→C中的决定属性B不是候选码,即C传递依赖于候选码A。
- 可将r( R )分解为r1(R1)=r1(A, B)、r2(R2)=r2(B, C)。
r1(R1)的候选码为A,r2(R2)的候选码为B。 - 则分解得到的r1(R1)和r2(R2)都属于3NF范式。
- [例5.7] r( R )=r(A, B, C, D, E),函数依赖集F={AB→C, B→D, C→E}。r( R )的候选码为AB,r( R )∉2NF。
- 因为函数依赖B→D中的决定属性B只是候选码的一部分,即D部分依赖于候选码AB;另外E传递依赖于候选码AB。
- r( R )分解为r1(R1)=r1(A, B, C)、r2(R2)=r2(B, D)、r3(R3)=r3(C, E)
- r1(R1)的候选码为AB,r2(R2)的候选码为B,r3(R3)的候选码为C。 它们都属于3NF范式。
- [例5.8] r( R )=r(A, B, C),函数依赖集F={AB→C, C→A}. r( R )的候选码为AB或BC,r( R )∈3NF。
- 因为关系模式r( R )没有非主属性,也就不可能有非主属性对候选码的部分依赖和传递依赖。
Boyce-Codd范式(BCNF)
- 基于函数依赖理论,关系模式可分成:
- 第一范式(1NF):所有属性都是原子的;
- 第二范式(2NF):不存在非主属性对候选码的部分依赖;
- 第三范式(3NF):不存在非主属性对候选码的传递依赖。
- Boyce-Codd范式(BCNF):?
- 定义5.9 给定关系模式r( R )∈1NF,函数依赖集F,若F+(表示F的闭包,详见5.4.1节)中的所有函数依赖α→β (α⊆R,β⊆R)至少满足下列条件之一:
- α→β 是平凡函数依赖(即β⊆α);
- α是r( R )的一个超码(即α中包含r( R )的候选码)。
——即起决定作用的属性必须是超码!
则称r( R )属于Boyce-Codd范式,记为r( R )∈BCNF。
- 换句话说,在关系模式r( R )中,如果F+中的每一个非平凡函数依赖的决定属性集α都包含候选码,则r( R )∈BCNF。
- 特别说明:为确定r( R )是否满足BCNF范式,必须考虑F+而不是F中的每个函数依赖。
- 决定因素必包含码!
- 从函数依赖角度可得出,一个满足BCNF的关系模式必然满足下列结论:( 如果α→β 非平凡, 则α是r( R )的一个超码)
- 所有非主属性都完全函数依赖于每个候选码;
- 所有主属性都完全函数依赖于每个不包含它的候选码;
- 没有任何属性完全函数依赖于非候选码的任何一组属性。
- BCNF范式排除了:
- 任何属性(包括主属性和非主属性)对候选码的部分依赖和传递依赖;
- 主属性之间的传递依赖。
Boyce-Codd范式判断举例
- [例5.9] r( R )=r(A, B, C),F={A→B, B→C}。
- r( R )的候选码为A,r( R )∉BCNF,因为函数依赖B→C中的决定属性B不是超码。
- [例5.10] r( R )=r(A, B, C),F={AB→C, C→A}。
- r( R )的候选码为AB或BC,r( R )∉BCNF,因为C→A的决定属性C不是超码。
- [例5.11] r( R )=r(A, B, C),F={AB→C, BC→A}。
- r( R )的候选码为AB或BC,r( R )∈BCNF,因为两个函数依赖中的决定属性AB或BC都是r( R )的候选码。
Boyce-Codd范式分解
- 对于非BCNF范式的关系模式,可通过分解进行规范化,以消除部分依赖和传递依赖。
- 例如,对于例5.9 (r( R )=r(A, B, C), F={A→B, B→C}, 候选码为A),可分解为:
r1(R1)=r1(A, B), r2(R2) =r2(B, C) (F1={A→B}、 F2={B→C})
或 r1(R1)=r1(A, B), r2(R2) =r2(A, C) (F1={A→B}、 F2={A→C})- 显然,这两种分解得到的r1(R1)和r2(R2)都属于BCNF范式,且都是无损分解(分解后的公共属性是一个关系的候选码)。
- 但是,后一种分解不是保持依赖分解(参见例5.23) 。
- 因此,满足BCNF范式的模式分解,可能不是保持依赖分解。
第三范式(3NF) ——仅仅是码——定义2
- 定义5.10 给定关系模式r( R )∈1NF,函数依赖集F,若对F+中的所有函数依赖α→β (α⊆R, β⊆R)至少满足下列条件之一:
- α→β是平凡函数依赖(即β⊆α);
- α是r( R )的一个超码(即α中包含r( R )的候选码);
- β-α中的每个属性是r( R )的候选码的一部分(即主属性)。
则称r( R )属于第三范式,记为 r( R )∈3NF。
- 3NF与BCNF范式的区别在于第3个条件:
- β-α中的每个属性是r( R )的候选码的一部分。
- 放松之处:
- 允许存在主属性对候选码的传递依赖和部分依赖。
- 允许存在主属性对候选码的传递依赖和部分依赖。
- 注意:如果β-α 中的每个属性是r( R )的候选码的一部分,那么α 中也一定包含候选码的一部分,即α 不可能全是非主属性(即α 中一定包含主属性)。
- 不妨假设α∩β = ∅,α→β是非平凡函数依赖,且不存在无关属性。
- 如果β是候选码,由于α→β ,那么α是超码(包含候选码),因此α 中一定包含主属性。
- 否则,设βγ 是候选码,有(βγ )+=R; 由于α→β ,那么
(αγ )+=R,即αγ 是超码(包含候选码) 。由于βγ 是候选码,即γ 不能单独构成候选码,因此α 中一定包含主属性。
- 注意:3NF的第3个条件不要求β -α中的每个属性必须包含在r( R )的一个候选码中。 因此,当r( R )有多个候选码时, β -α中的每个属性可以包含在r( R )的不同候选码中。
- 总之,非主属性对候选码的部分依赖问题在2NF中解决了, 而非主属性对候选码的传递依赖问题由3NF来解决!
- 即不允许非主属性起决定使用——仅仅是码。
- [例5.12] r( R )=r(A, B, C),F={AB→C, C→A}。r( R )的候选码为AB或BC,由[例5.8]和[例5.10]可知,r( R )∈3NF, 但 r( R )∉BCNF。
3NF与BCNF比较
- BCNF比3NF严格。
- BCNF要求所有的非平凡函数依赖α→β中的α是超码,而3NF则放松了该约束,允许α不是超码。
- 若关系模式属于BCNF范式就一定属于3NF范式。反之则不一定成立。
- 3NF存在数据冗余和异常问题,而BCNF是基于函数依赖理论能够达到的最好关系模式。
- BCNF范式分解是无损分解,但不一定是保持依赖分解; 而3NF分解既是无损分解,又是保持依赖分解。
小结
- 关系数据理论
- 问题的提出
- 关系数据理论有什么作用?
- 函数依赖
- 什么是函数依赖?
- 什么非平凡的函数依赖?
- 什么完全(部分)函数依赖?
- 什么传递函数依赖?
- 范式
- 1NF
- 2NF:所有非主属性都完全函数依赖于r( R )的候选码
- 3NF:所有非主属性都直接函数依赖于r( R )的候选码。
- BCNF:决定因素必包含码。
5.4 函数依赖理论
函数依赖集闭包
- 对于给定关系模式r(R, D, DOM, F)(简记为 r( R ))及其函数依赖集F,有时只考虑给定的函数依赖集是不够的,而需要考虑在r( R )上总是成立的所有函数依赖。
- [例5.13] 给定关系模式r( R )=r(A, B, C)及函数依赖集
F={A→B, B→C},证明A→C成立。
证明:假设对于关系实例r中的任意两个元组ti, tj, i≠j,满足ti[A]=tj[A]。由于存在A→B,则可推出ti[B]=tj[B]。
又由于B→C,则又可推出ti[C]=tj[C]。
因此,ti[A]=tj[A] => ti[C]=tj[C]。按定义5.1有A→C。证毕。
(重要概念)
- 定义5.11 若给定函数依赖集F,可以证明其他函数依赖也成立,则称这些函数依赖被F逻辑蕴涵。
- 定义5.12 令F为一函数依赖集,F逻辑蕴涵的所有函数依赖组成的集合称为F的闭包,记为F+。
- 函数依赖集F的闭包计算方法
- Armstrong公理的推理规则
Armstrong公理及推论(理解)
- Armstrong公理
- 自反律(reflexivity rule):若存在β⊆α,则有α→β
- 增补律(augmentation rule):若存在α→β,则有γα→γβ
- 传递律(transitivity rule):若存在α→β且β→γ,则有α→γ
- Armstrong公理三个推论
- 合并律(union rule):若有α→β且α→γ,则有α→βγ
- 分解律(decomposition rule):若有α→βγ,则有α→β和α→γ
- 伪传递律(pseudotransitivity rule):若有α→β且βγ→δ,则有αγ→δ
函数依赖集闭包计算举例
- [例5.14] 令r( R )=r(A, B, C, G, H, I),函数依赖集F={A→B, A→C, CG→H, CG→I, B→H}。我们可列出F+中的几个依赖:
- 由传递律可得A→H,因为A→B且B→H;
- 由合并律可得CG→HI,因为CG→H,CG→I;
- 由伪传递律可得AG→I,因为A→C且CG→I。
- 还可以使用上述规则推导出更多的函数依赖,可尝试推导。
属性集闭包(重要概念)
- 如果想要判断一个给定的函数依赖α→β是否在函数依赖集F的闭包中,不用计算F+就可以判断出来。
- 定义5.13 令r( R )为关系模式,F为函数依赖集,A⊆R,则称在函数依赖集F下由A函数确定的所有属性的集合为函数依赖集F下属性集A的闭包,记为A+。
- 属性集闭包的计算算法:
属性集闭包计算举例(划重点)
- [例5.15] r( R )=r(A, B, C, G, H, I),F={A→B, A→C, CG→H, CG→I, B→H},计算(AG)+。
- 算法的执行步骤如下:
步骤 FD closure
1. 赋初值 AG
2. A→B ABG
3. A→C ABCG
4. CG→H ABCGH
5. CG→I ABCGHI- 结果为:closure=ABCGHI。
- 算法在外循环的第一次执行过程中,当内循环循环执行4次(即遍历到F中的函数依赖CG→I)后,closure就已经为ABCGHI(即R),算法终止。
- 最后结果为:(AG)+=ABCGHI。
- 算法的执行步骤如下:
计算属性集闭包的作用
- 计算属性集闭包的作用可归纳如下:
- 验证α→β是否在F+中:看是否有β ⊆αF+。
- 判断α是否为r( R )的超码:计算α+,看其是否包含R的所有属性。如(AG)+=ABCGHI,则AG为r( R )的超码。
- 判断α是否为r( R )的候选码:若α是超码,可检验α包含的所有子集的闭包是否包含R的所有属性。若不存在任何这样的属性子集,则α是r( R )的候选码。
- 计算F+。对于∀ γ ⊆R,可通过找出γ+;
则有:对∀ S ⊆ γ +,可输出一个 γ → S。
判断属性集是否为候选码举例
- [例5.16] r( R )和F见例5.15,判断AG是否为r( R )的候选码.
- 例5.15已计算出(AG)+=ABCGHI,则还要进一步分别计算A+和G+。
- 经计算得,A+=ABCH、G+=G,它们都不包含R的所有属性。因此,AG为r( R )的候选码。
- 对于一个给定的关系模式r( R )及函数依赖集F,如何找出它的所有候选码?
- 这是基于函数依赖理论和范式概念判断该关系模式是否是“好”模式的基础;
- 也是对一个“不好”的关系模式进行分解的基础。
判断属性集是否为候选码
- 给定关系模式r( R )及函数依赖集F,找出它的所有候选码的一般步骤如下:(划重点:会运用!)
- 找出函数依赖集F中在所有函数依赖右方都没有出现的属性集X,属性集X中的属性都一定是候选码中的属性。
- 找出F中在所有函数依赖右方出现但左方没有出现的属性集Y,属性集Y中的属性都不可能是候选码中的属性。
- 如果X非空,则基于F计算X+,并开始发现所有候选码:
- 如果X+=R,则X是关系r( R )的唯一候选码;
- 如果X+≠R,则
- 首先,试着发现是否能够通过增加1个属性与X联合起来构成候选码, 例如,若存在α∈R-X-Y,使 (X∪{α})+=R,则(X∪{α})是关系r( R )的一个候选码;继续试着增加另一个属性,若存在β∈R-X-Y-{α},使(X∪{β})+=R,则(X∪{β})是关系r( R )的另一个候选码;……。记找到的所有属性的集合为Z,即∀α∈Z,使(X∪{α})+=R。
- 接下来,还可以试着发现是否能够通过增加2个或多个属性与X联合起来构成候选码,例如, 若存在{α, β}⊆R-X-Y-Z,使 (X∪{α, β})+=R; 则(X∪{α, β})也是关系r( R )的一个候选码;……。
- 如果X为空,则从F中的每一个函数依赖α→u开始(先从左边属性较少的函数依赖开始):
- 如果α+=R,则α是关系r( R )的一个候选码;
- 如果α+≠R,类似地,试着发现是否能够通过增加1个属性与α联合起来构成候选码;再试着发现是否能够通过增加2个或多个属性与α联合起来构成候选码。
求解候选码的方法
先对属性分类:
- 对于给定的关系模式R(U,F) ,可以将其属性分为四类:
- 1、仅在F函数依赖左部出现的属性L类
- 2、仅在F函数依赖右部出现的属性R类
- 3、在F函数依赖左右两边均未出现的属性N类
- 4、在F函数依赖左右两边均出现的属性LR类
有用的定理和推论
- 定理1:对于给定的R(U,F),如果K是L 类属性,则K 必为R的任一候选码的成员。
- 推论1:对于给定的R(U,F),K是L类属性,且KF+=U,则K必为R的唯一候选码。
- 定理2:对于给定的R(U,F),如果K 是R类属性,则K不在R的任何候选码中。
- 定理3:对于给定的R(U,F),如果K是N 类属性,则K 必包含在R的任一候选码中。
- 推论2:对于给定的R(U,F),如果K是N类和L 类属性组成的属性集,且KF+=U,则K 必为R的唯一候选码。
判断属性集是否为候选码举例
- [例5.17] 给定关系模式r( R )=r(A, B, C, D),函数依赖集F={B→C, D→A},找出r( R )的所有候选码。
- 属性集BD没有在函数依赖的右部出现,故BD为候选码的一部分;
- 由于(BD)+=BDCA=R,所以BD为关系模式r( R )的唯一候选码。
- [例5.18] 给定关系模式r( R )=r(A, B, C, D, E),函数依赖集F={A→B, BC→E, ED→A},找出r( R )的所有候选码。
- 属性集CD没有在函数依赖的右部出现,故X=CD为候选码的一部分;
- 因(CD)+=CD≠R,故CD不是候选码;
- 因没有在函数依赖右部出现但左部不出现的属性,故Y=∅;
- 在集合R-X-Y=ABE中寻找与X联合构成候选码的属性(集):
- ({A, CD})+=ACDBE=R,故ACD为候选码;
- ({B, CD})+=BCDEA=R,故BCD为候选码;
- ({E, CD})+=ACDBE=R,故ECD为候选码。
- 因此,关系模式r( R )的候选码有ACD、BCD和ECD。
- [例5.19] 设关系模式R={A, B, C, D, E, G},函数依赖集F={B→ADE, A→BE, AC→G, BC→D },找出r( R )的所有
候选码。- 因C没有在函数依赖的右部出现,故X=C为候选码的一部分;
- 因C+=C≠R,故C不是候选码;
- 在函数依赖右部出现但左部不出现的属性有DEG, 故Y=DEG;
- 在R-X-Y=AB中寻找与X联合起来构成候选码的属性(集):
- ({A, C})+=ACBEGD=R,故AC为候选码;
- ({B, C})+=BCADEG=R,故BC为候选码。
- 因此,关系模式r( R )的候选码有AC和BC。
无损连接分解
- 定义5.18 给定关系模式r( R )及函数依赖集F,记r1(R1)、r2(R2) 为由r( R )分解得到的子模式,如果对任意一个满足函数依赖集F的关系实例r都有
则称该分解对于F是无损连接的。- 无损连接分解能够根据分解后的关系通过连接还原原来的关系实例。
- 如何判定一个分解是否是无损连接的?
- 定义5.19 (判别无损分解!) 给定关系模式r( R )及函数依赖集F,则将r( R )分解成r1(R1)、r2(R2)的分解是无损连接分解,当且仅当F+ 包含函数依赖R1∩R2→R1或R1∩R2→R2.
- 即:在F下,R1 ⊆ (R1∩R2)+ 或 R2 ⊆ (R1∩R2)+。
- 因此,当一个关系模式分解为两个关系模式时,该分解为无损连接分解的充要条件是两分解关系的公共属性包含r1(R1)的码 或 r2(R2)的码。
- 即: R1∩R2 是关系 r1(R1) 或 r2(R2) 的超码。
- [例5.22] 假设关系模式r( R )=r(A, B, C, D, E), F ={A→BC, CD→E, B→D, E→A},则可将r( R )进行两种不同的分解:
- 分解1:r1(R1)=r1(A, B, C),r2(R2)=r2(A, D, E);
- 分解2:r1(R1)=r1(A, B, C),r2(R2)=r2(C, D, E)。
- 对于分解1,R1∩R2=A,且A→R1,故此分解是无损连接分解。
- 而对于分解2,R1∩R2=C,且C→/R1、C→/R2,故此分解不是无损连接分解。
如果将关系模式r( R )分解为M个(M>2)子关系模式r1(R1)、r2(R2)、…、rM(RM),且R1∪R2 ∪ …∪ RM =R 。则如何判断此分解是不是无损连接分解?
- 方法一:逐步连接判断法
- 先选择满足定义5.19 (即满足无损连接条件)的2个子关系模式进行无损连接,不仿假设将子关系模式r1(R1)和r2(R2)进行无损连接,并将连接后的关系模式记为r12(R12);
- 对连接后剩下的子关系模式r12(R12)、r3(R3)、…、rM(RM),重复上面的连接步骤,直到连接为一个关系模式——则该分解是无损连接分解;或者剩下的任意2个子关系模式之间都无法进行无损连接 ——则该分解是有损连接分解。
- 方法二:表格判断法(参考王珊《数据库系统概论》第5版)
- 设R={A1, A2, …, AN},F={FD1, FD2, …, FDK}。
- 建立一张M行、N列的判断表,第i行对应子关系模式ri(Ri) (1≤i≤M), 第j列对应属性Aj (1≤ j≤N)。
- 若Ri中包含属性Aj,则在第i行、j列处填上aj,否则填上bij。
- 对F的一次扫描:对F中每一个函数依赖αk→Aj (1≤ k≤K),找到αk的所有属性所对应的列中具有相同符号的那些行。考察这些行中属性Aj列(假设为第j列)的元素,若其中有aj,则全部改为aj ;否则全部改为btj,t是这些行中的最小行号。
- 注意:若某个bij被更改为btj,则该表的第j列中凡是bij的符号(不限于开始找到的那些行)均应相应地更改为btj。
- 重复对F进行扫描,直至某一行成为a1, a2, …, aN, 或表中内容不再发生变化。
- 如果某一行成为a1, a2, …, aN,则是无损连接分解;否则是有损连接分解。
- 说明:通常可省略bij符号的标示。
- [例] 设关系模式r(ABCDEF),函数依赖集为:F={ED→BF,D→C,F→AE,E→F},判断r的一个分解ρ={ r1(CD),r2(AEF),r3(BDF),r4(BE) }是否为无损连接分解?
- 由于ED两列中没有整体上具有相同符号的行,因此跳过该函数依赖。
- 由于ED两列中没有整体上具有相同符号的行,因此跳过该函数依赖。
保持依赖分解
- 关系数据库模式分解的另一个目标是保持依赖。
- 定义5.20 给定关系模式r( R )及函数依赖集F,r1(R1), r2(R2), …, rn(Rn)为r( R )的分解。F在Ri的投影为闭包F+中所有只包含Ri属性的函数依赖的集合,记为Fi。即如果α→β在Fi中,则α和β的所有属性均在Ri中。
- 定义5.21 (判别保依分解!) 称具有函数依赖集F的关系模式r( R )的分解r1(R1), r2(R2), …, rn(Rn)为保持依赖分解,当且仅当(F1∪F2∪…∪Fn)+=F+。
- [例5.23] 设关系模式r( R )=r(A, B, C),F ={A→B, B→C},有两种分解:
- r1(R1)=r1(A, B)、r2(R2) =r2(B, C)
- F1={A→B}、F2={B→C}
- 该分解保持函数依赖,因为 (F1∪F2)+=F+。
- r1(R1)=r1(A, B)、r2(R2) =r2(A, C)。
- F1={A→B}、F2={A→C} (注:{A→C} ⊆F+)
- 该分解不保持函数依赖。因为分解后函数依赖B→C被丢失。
- r1(R1)=r1(A, B)、r2(R2) =r2(B, C)
5.5 模式分解算法
- 数据库设计目标为(基于函数依赖):
- BCNF
- 无损连接
- 保持依赖
- 如果不能同时达到这3个目标,就需要根据实际应用需求在BCNF和3NF中做出选择。
- 主要模式分解算法
- BCNF分解
- 3NF分解
BCNF分解
- 设r( R )为关系模式,r( R )∉BCNF,若非平凡函数依赖α→β 违反了BCNF的函数依赖条件(即α不是超码),则将r( R )分解为r1(R1)和r2(R2),其中:
- R1=αβ F1={α→β} —— 如果α∩β=∅,则α是候选码
- R2=R-(β-α) —— 如果α∩β=∅,则R2=R-β
- 若r2(R2)不属于BCNF,则继续分解下去,直到所有结果模式都为BCNF。
- (1) r( R)=r(A,B,C,D), F1={C→D,C→A,B→C};
- 错误分解
- 正确分解
- 错误分解
BCNF分解算法
- BCNF分解算法的形式化描述如下:
BCNF分解举例
-
[例5.24] r( R )=r(A, B, C),F={AB→C, C→A},判断关系模式r( R )是否属于BCNF范式?如果不是,则进行BCNF分解。
- [例5.10]已经证明r( R )∉BCNF(因为候选码为AB或BC,所以C→A的决定属性C不是超码)。按上述算法,r( R )可分解为
- r1(R1)=r1(A, C),F1={C→A}
——该关系r1(R1)中,C是候选码 - r2(R2)=r2(B, C),F2={∅}
——该关系r2(R2)中,BC是候选码
- r1(R1)=r1(A, C),F1={C→A}
- 分解后的r1(R1)和r2(R2)都属于BCNF,不需再做分解。
- 注意:F中的函数依赖关系AB→C ,在分解后丢失了!
- [例5.10]已经证明r( R )∉BCNF(因为候选码为AB或BC,所以C→A的决定属性C不是超码)。按上述算法,r( R )可分解为
-
[例5.25] r( R )=r(A, B, C, D, G, H),F={A→BC, DG→H , D→A}, r( R )是否属于BCNF范式?如果不是,则进行BCNF分解。
- r( R )∉BCNF(因为候选码为DG ,所以A→BC的决定属性A不是超码)。按上述算法,r( R )可分解为
- r1(R1)=r1(A, B, C), F1={A→BC} —— A是候选码
- r2(R2)=r2(A, D, G, H),F2={DG→H , D→A}—DG是候选码
- r2(R2)∉BCNF(因为D→A的决定属性D不是超码)。按上述算法,r2(R2)可分解为
- r21(R21)=r21(D, A), F21={D→A} —— D是候选码
- r22(R22)=r22(D, G, H), F22={DG→H} —— DG是候选码
- 最后,r1(A, B, C)、r21(D, A)和r22(D, G, H)都属于BCNF。
- r( R )∉BCNF(因为候选码为DG ,所以A→BC的决定属性A不是超码)。按上述算法,r( R )可分解为
BCNF分解
- 上述算法得到的分解不仅是BCNF分解,而且是无损分解(但可能不是保持函数依赖分解)。
- 算法中使用的函数依赖集是F+而不是F。
- 用该算法生成的BCNF分解不是唯一的。
5.6 数据库模式求精
模式求精的必要性
- E-R图设计是一个复杂且主观的过程,并且有些约束关系并不能通过E-R图来表达。一些不“好”的关系模式可能忽略数据之间的约束关系而产生冗余,特别是在大型数据库模式设计时更是如此。
- 另外,关系模式不一定都是严格地由E-R图转换得到,也可能是设计者的即席产生。因此,有必要对关系模式进行模式求精。
- 模式求精是运用关系理论(如函数依赖理论、多值依赖理论等)对已有关系模式进行结构调整、分解、合并和优化的过程,以满足应用系统的功能及性能等需求。
模式求精步骤
- 基于函数依赖理论的模式求精步骤:
- 确定函数依赖。根据需求分析得到的数据需求,确定关系模式内部各属性之间以及不同关系模式的属性之间存在的数据依赖关系。
- 确定关系模式所属范式。按照数据依赖关系对关系模式进行分析,检测是否存在部分依赖或传递依赖,以确定该模式属于第几范式。
- 分析是否满足应用需求。按照需求分析得到的数据处理要求,分析现有模式是否满足应用需求,并决定是否需要进行模式合并或分解。
- 模式分解。根据范式要求(是选择BCNF还是3NF),运用规范化方法将关系模式分解成所要求的关系模式。
- 模式合并。在分解过程中可能进行模式合并。如当查询经常涉及到多个关系模式的属性时,系统将经常进行连接操作,而连接运算的代价是相当高的。此时,可考虑将这几个关系合并为一个关系。
模式求精举例
- [例5.29] 假设大学选课系统中课程与教师的关系模式设计为:
- CourseTeacher (courseNo, courseName, creditHour, courseHour,
teacherNo, teacherName, title, degree, teachNumber)
其中属性集{courseNo, teacherNo}是主码。试对该模式进行模式求精,以达到BCNF/3NF范式要求。
- CourseTeacher (courseNo, courseName, creditHour, courseHour,
- 步骤1. 分析函数依赖关系及判断范式
- 关系模式CourseTeacher存在以下函数依赖:
- courseNo → courseName, creditHour, courseHour
- teacherNo→ teacherName, title, degree
- {courseNo, teacherNo} → teachNumber
- 显然,存在非主属性对主码的部分依赖,故CourseTeacher不属于2NF范式,更不属于BCNF范式。
- 关系模式CourseTeacher存在以下函数依赖:
- 步骤2. 模式分解
- 由于存在部分函数依赖:courseNo → courseName, creditHour, courseHour,违背了BCNF/3NF条件,依BCNF/3NF分解算法,可将关系模式CourseTeacher分解为以下两个关系模式:
- Course (courseNo, courseName, creditHour, courseHour);
- Teaching (courseNo, teacherNo, teacherName, title, degree, teachNumber)
- 可验证关系模式Course已满足BCNF/3NF要求,且是无损分解(因为公共属性courseNo是关系模式Course的主码)。
- 而在关系模式Teaching中,由于存在部分函数依赖:teacherNo→ teacherName, title, degree,因此可以进一步分解为:
- Teacher (teacherNo, teacherName, title, degree)
- NewTeaching (courseNo, teacherNo, teachNumber)
- 可验证关系模式Teacher和NewTeaching都已满足BCNF/3NF要求,且是无损分解(因为公共属性teacherNo是关系模式Teacher的主码)。
- 由于存在部分函数依赖:courseNo → courseName, creditHour, courseHour,违背了BCNF/3NF条件,依BCNF/3NF分解算法,可将关系模式CourseTeacher分解为以下两个关系模式:
- 综合上述分解结果,关系模式CourseTeacher可以分解为如下满足BCNF/3NF要求的三个关系模式:
- Course (courseNo, courseName, creditHour, courseHour)
- Teacher (teacherNo, teacherName, title, degree)
- NewTeaching (courseNo, teacherNo, teachNumber)
- 模式求精是数据库设计过程中非常重要的一步,设计者应在关系数据理论的指导下检查和改进设计中存在的不足和缺陷,以保证最终的设计结果尽可能地满足应用需求。
总结
- 函数依赖定义(重点)
- 非平凡、部分(完全)、传递
- 范式(重点前三)
- 1NF、2NF、3NF、BCNF
- 函数依赖集闭包(重点),Armstrong公理(理解)。
- 函数依赖集F下属性集A的闭包(重点)
- 验证α→β是否在F+中;计算F+。
- 判断α是否为r( R )的超码、候选码 ——候选码的计算方法。
- 无损连接分解:R1∩R2是关系 r1(R1)或 r2(R2)的超码(理解)。
- 保持依赖分解: (F1∪F2∪…∪Fn)+=F+。
- BCNF:F+中非平凡函数依赖的决定属性集α都包含候选码.
- 不存在任何属性(包括主属性和非主属性)对候选码的部分依赖和传递依赖,以及主属性之间的传递依赖。
- 模式分解:是无损连接分解,可能不是保持依赖分解。
- 3NF:允许存在主属性对候选码的传递依赖和部分依赖。
- 模式分解:是无损连接分解,且是保持依赖分解。
- 模式分解算法
- BCNF分解;
- 模式求精
- 确定函数依赖;
- 确定关系模式所属范式;
- 分析是否满足应用需求;
- 模式分解;
- 模式合并。
计算候选码
判别范式级别
规范化