目录
一、问题提出
数据依赖与冗余
二、函数依赖
2.1定义
2.2函数依赖类型
2.2.1函数依赖
2.2.2平凡函数依赖与非平凡函数依赖
2.2.3完全函数依赖与部分函数依赖
2.2.4传递函数依赖
2.3函数依赖的推导
2.3.1 Armstrong公理
2.3.2属性集的闭包
2.3.3函数依赖集的极小覆盖
三、范式
3.1码
3.2范式种类
3.2.1 1NF
3.2.2 2NF
3.2.3 3NF与 BCNF
四、关系模式分解
4.1无损连接分解
4.2保持函数依赖的分解
五、关系模式分解成高级范式
5.1具有无损连接性的 BCNF分解
5.2具有无损连接性和保持函数依赖的 3NF分解
由于D、DOM与模式设计关系不大,本博客中把关系模式看作一个三元组:R
数据库设计的不好可能导致多个问题:冗余,修改异常,插入异常,删除异常
数据依赖是关于诸属性值之间内在相关性的陈述,它规定了关系模式的合法关系实例所必须满足的条件,可分为函数依赖和多值依赖
依赖和冗余是密不可分的:承认某种数据依赖,就能发现关系中的某些冗余;而不承认数据之间的依赖关系,也没理由认为某些信息是多余的
冗余的产生原因和处理总是联系在一起
字母表开头的大写字母 A,B,…,H表示单个属性
字母表尾部的大写字母 U,V,…,Z一般表示属性集,也可能是由单个属性构成的集合。U常用于表示关系的全部属性组成的集合
串接表示并。A1A2…An表示集合 {A1,A2,…,An},XY是 X Y的缩写,若 A是单个属性,X是属性集,则 XA或 AX表示 X {A}
R表示关系模式
r 表示关系,它是关系模式 R的某个实例
设R(U)是一个属性集U上的关系模式,X和Y是U的子集。若对于R(U)的任意一个可能的关系r,r 中不可能存在两个元组在X上的属性值相等, 而在Y上的属性值不等, 则称“X函数确定Y”或“Y函数依赖于X”,记作X→Y
解释:若在一张表中,属性或属性组X确定,必定能确定属性Y的值,则称Y函数依赖于X,记做X->Y
举例:在学生表ST中通过学号能唯一确定一个姓名,则姓名函数依赖于学号
学生表ST
学号 | 姓名 | 性别 |
---|---|---|
1 | 张三 | 男 |
定义:设一个关系为R(U),X和Y为属性集U上的子集,若X→Y且X不包含Y,则称X→Y为非平凡函数依赖,否则若X包含Y则必有X→Y,称此X→Y为平凡函数依赖
举例:在学生表ST中,学号总能函数决定它本身,记作“学号→学号”,此为平凡函数依赖。(学号,性别)->性别与(学号,性别)->学号也是平凡函数依赖
通常,我们主要讨论的是非平凡函数依赖:如学生表ST中学号函数决定的其他属性都是非平凡函数依赖
1、完全函数依赖
定义:设X,Y是关系R的两个属性集合,X' 是X的真子集,存在X→Y,但对每一个X' 都有X' !→Y,则称Y完全函数依赖于X
解释:在一张表中,若 X → Y,且对于 X 的任何一个真子集(假如属性组 X 包含超过一个属性的话),X' → Y 不成立,那么我们称 Y 对于 X 完全函数依赖
举例:在成绩表SG中,成绩完全函数依赖于(学号,CID(课程号))
成绩表SG
学号 | CID(课程号) | 成绩 |
---|---|---|
1 | 1 | 80 |
2、部分函数依赖
定义:设X,Y是关系R的两个属性集合,存在X→Y,若X' 是X的真子集,存在X' →Y,则称Y部分函数依赖于X
解释:假如 Y 函数依赖于 X,但同时 Y 并不完全函数依赖于 X,那么我们就称 Y 部分函数依赖于 X
举例:学生表ST中(学号,姓名)->性别,但是存在学号->性别,所以称性别部分依赖于(学号,姓名)
定义:设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X
解释:假如 Z 函数依赖于 Y,且 Y 函数依赖于 X (严格来说还有一个X 不包含于Y,且 Y 不函数依赖于Z的前提条件),那么我们就称 Z 传递函数依赖于 X
举例:关系S1(学号,系名,系主任),学号 → 系名,系名 → 系主任,并且系名 !→ 学号,所以学号 → 系主任为传递函数依赖
自反律:如果 Y X U,则 X->Y成立
增广律:如果 X->Y成立,并且 Z U,则 XZ->YZ成立
传递律:如果 X->Y和 Y->Z成立,则 X->Z成立
附加的推理规则
合并规则:如果 X->Y和 X->Z成立,则 X->YZ成立
伪传递规则:如果 X->Y和 WY->Z成立,则 WX->Z成立
分解规则:如果 X->Y成立,并且 Z Y,则 X->Z成立
使用 Armstrong公理由 F导出的函数依赖都被 F逻辑蕴含
1、定义
对F,F+中所有X→A的A的集合称为X的闭包,记为X+。可以理解为X+表示所有X可以决定的属性
2、计算
输入:关系模式 R(U)上的函数依赖集 F和属性集 X U
输出:属性集 X闭包X+
方法
result=X;
repeat
for(F中的每个函数依赖 Y->Z) do
if(Y包含于 result) then result=result U Z;
until (result不改变);
输出 result;
例:R={A,B,C,G,H,I},F={A->B,A->C,CG->H,CG->I,B->H},求 (AG)+
解:
result=AG 先把式子本身包含在闭包中
result=ABCG (A->C and A->B)
result=ABCGH (CG->H and CG AGBC)
result=ABCGHI (CG->I and CG AGBCH)
1、定义
如果函数依赖集F满足以下条件,则称F为一个极小函数依赖集,也称为最小依赖集或最小覆盖
2、计算
输入:函数依赖集 F
输出:函数依赖集 F的极小覆盖 Fm
方法
例:R={A,B,C,D,E,F},F={AD→E,AC→E,BC→F,BCD→A,BCD→F,BD→A,AB→F,A→C},求F的最小函数依赖集
解:
- 对于AD→E,因为(AD)的闭包 = ADCE, 又因为ACDE 包含E,所以AD→E 冗余 F1={AC→E,BC→F,BCD→A,BCD→F,BD→A,AB→F,A→C}
- 对于AC→E,因为(AC)的闭包=AC,又因为AC不包含E,所以AC→E不冗余 F2={AC→E,BC→F,BCD→A,BCD→F,BD→A,AB→F,A→C}
- 对于BC→F,因为(BC)的闭包=BC,又因为BC不包含F,所以BC→F 不冗余 F3={AC→E,BC→F,BCD→A,BCD→F,BD→A,AB→F,A→C}
- 对于BCD→A,因为(BCD)的闭包 = ABCDEF,又因为ABCDEF包含A,所以BCD→A 冗余 F4={AC→E,BC→F,BCD→F,BD→A,AB→F,A→C}
- 对于BCD→F,因为(BCD)的闭包 = ABCDEF,又因为ABCDEF包含F,所以BCD→F 冗余 F5={AC→E,BC→F,BD→A,AB→F,A→C}
- 对于BD→A,因为(BD)的闭包 = BD,又因为BD不包含A,所以BD→A 不冗余 F6={AC→E,BC→F,BD→A,AB→F,A→C}
- 对于AB→F,因为(AB)的闭包 = ABCDEF,又因为ABCDEF包含F,所以AB→F 冗余 F7={AC→E,BC→F,BD→A,A→C}
- 对于A→C,因为A的闭包=A,又因为A不包含C,所以A→C 不冗余
故F的最小函数依赖集为{AC→E,BC→F,BD→A,A→C}
设K为R<U,F>中的属性或属性组合。若K U,则K称为R的一个候选码
如果U部分函数依赖于K,则K称为超码。候选码是最小的超码,即K的任意一个真子集都不是候选码
若关系模式R有多个候选码,则选定其中的一个做为主码
包含在任何一个候选码中的属性 ,称为主属性,其余称为非主属性
整个属性组是码,称为全码
关系模式 R中属性或属性组X 并非 R的码,但 X 是另一个关系模式的码,则称 X 是R 的外码
范式是符合某一级别的关系模式的集合
各种范式之间存在联系
一个低一级范式的关系模式,通过模式分解可以转换为若干个高一级范式的关系模式的集合,这种过程就叫规范化
条件:每个分量必须是不可分开的数据项
解释:在一列中不能插入两个及以上不同属性的值
定义:对于任意的非平凡函数依赖 X->A F+,必须满足下列两个条件之一:A是主属性,或 X不是 R的任何码的真子集
解释:第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一地区分。选取一个能区分每个实体的属性或属性组,作为实体的唯一标识,即要有主码
举例:如果在成绩表SG中添加一列姓名变成下面这样,SG表的主码是学号加CID(课程号),但是(学号)->姓名,所以姓名部分函数依赖于(学号,CID(课程号)),不符合2NF
成绩表SG
学号 | CID(课程号) | 成绩 |
---|---|---|
1 | 1 | 80 |
成绩表SG 2.0
学号 | CID(课程号) | 成绩 | 姓名 |
---|---|---|---|
1 | 1 | 80 | 张三 |
1、3NF
定义:对于任意的非平凡函数依赖 X->A F+,必须满足下列两个条件之一:A是主属性,或 X是 R的码(在2NF基础上消除传递依赖)
解释:第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主属性信息
举例:如果在课程表SC中添加一列老师姓名,变成如下,存在CID(课程号)->TID(授课老师ID),TID(授课老师ID)->教师姓名,TID(授课老师ID) !->CID(课程号),所以教师姓名传递函数依赖于CID(课程号),不满足3NF,但是满足2NF,主码是CID
课程表SC
CID (课程号) | 课程名称 | TID(授课老师ID) | 学分 |
---|---|---|---|
1 | 数学 | 1 | 2 |
课程表SC 2.0
CID (课程号) | 课程名称 | TID(授课老师ID) | 学分 | 教师姓名 |
---|---|---|---|---|
1 | 数学 | 1 | 2 | 李四 |
2、BCNF
对于任意的非平凡函数依赖 X->A F+,X是 R的码
范式总结
检测无损分解的连接性
输入:关系模式 R(A1,A2,...,An),R的函数依赖集 F和分解 ={R1,R2,...Rk}
输出: 是否是关于 F的无损连接分解的判定
方法
例:关系模式 R(A,B,C,D,E)的分解是 ={R1(A,B,C), R2(C.D), R3(D,E)},其中 R的函数依赖集 F={AB->C,C->D,D->E}
解:
构造初始表
A
B
C
D
E
a1
a2
a3
b14
b15
b21
b22
a3
a4
a5
b31
b32
b33
a4
a5
得出最终表
A
B
C
D
E
a1
a2
a3
a4
a5
b21
b22
a3
a4
a5
b31
b32
b33
a4
a5
第一行是a1a2a3a4a5,所以 是无损连接分解
如果 R被分解成两个关系模式 R1和 R2,可用如下简单方法进行判定
设 ={R1,R2}是关系模式 R的一个分解,F是 R上的函数依赖集。 关于 F是无损连接分解当且仅当:
(R1 R2) -> (R2 - R1) 或 (R1 R2) -> (R2 - R1)
输入:关系模式 R的函数依赖集 F和分解 ={R1,R2,...,Rk}
输出: 是否保持函数依赖的判定
方法
for (每个 X->Y包含于 F) do
begin
if (不存在 i使得 XY包含于 Ri) then
--检验 X->Y是否被分解 p所保持
begin
Z=X;
repeat
for i=1 to k do
Z=Z 并 ((Z 交 Ri)+ 交 Ri);
until (Z不发生变化);
if (Y不是 Z的子集) then -- X->Y不被分解 p所保持
return p不是保持函数依赖的分解;
end;
end;
无损连接是对关系模式分解的基本要求。不具有无损链接性的分解是有害的,因为分解前后的关系模式可能不能反应相同的现实世界
保持函数依赖的分解是对关系模式分解的进一步要求。实践中应当在确保无损连接性的前提下尽可能地追求保持函数依赖。如果两者不可兼得,优先考虑无损连接分解
任意关系模式都可以无损连接地分解成 BCNF
如果要求分解保持函数依赖,或者保持函数依赖并且具有无损连接性,则只能保证分解到 3NF
只包含两个属性的关系模式一定是 BCNF
输入:关系模式 R及 R的函数依赖集 F
输出:R的 BCNF分解,它关于 F具有无损连接性
方法
result={R}
while (存在 Ri属于 result,但 Ri不是 BCNF)
begin
找出 Ri中满足如下条件的非平凡函数依赖:X->Y属于F+,且 X不是 Ri的超码;
result={Ri1(XY),Ri2(Ri-Y)}; --之后分别对新产生的模式进行该操作
end
return result;
例、关系模式R,其中:U={A,B,C,D,E},F={A→C,C→D,B→C,DE→C,CE→A},将其分解成BCNF并保持无损连接
解:
L: ACBDE R: CDA N: LR: ACD
①令ρ={R(U,F)}
②ρ中不是所有的模式都是BCNF,转入下一步
③分解R:R上的候选关键字为BE(因为所有函数依赖的右边没有BE)
考虑A→C函数依赖不满足BCNF条件(因A不包含候选键BE),将其分解成R1(AC)、R2(ABDE)
计算R1和R2的最小函数依赖集分别为:F1={A→C},F2={B→D,DE→D,BE→A}
其中B→D是由于R2中没有属性C且B→C,C→D;DE→D是由于R2中没有属性C且DE→C,C→D;BE→A是由于R2中没有属性C且B→C,CE→A。又由于DE→D是蕴含关系,可以去掉,故F2={B→D, BE→A}
对于给定的关系模式 R,先计算 F的极小覆盖(转顶部链接内容:2.3.3函数依赖集的极小覆盖)
对于极小覆盖中的每个函数依赖,只要依赖的左侧相同,则合并这些函数依赖的所有属性构成一个单独的模式
如果关系模式 R中存在没有出现在函数依赖集中的元素,这些元素合并构成一个单独的模式
如果上面两步得出的结果中不包含候选码,则候选码单独构成一个模式(尽管候选码被拆散到多个模式中也不算)
例、关系模式R,其中U={C,T,H,R,S,G},F={CS→G,C→T,TH→R,HR→C,HS→R},将其分解成3NF并保持函数依赖
解:
(一)计算F的最小函数依赖集
①利用分解规则,将所有的函数依赖变成右边都是单个属性的函数依赖。由于F的所有函数依赖的右边都是单个属性,故不用分解
②去掉F中多余的函数依赖 F={CS→G,C→T,TH→R,HR→C,HS→R}
去掉F中各函数依赖左边多余的属性(只检查左部不是单个属性的函数依赖),没有发现左边有多余属性的函数依赖
故最小函数依赖集为:F={CS→G,C→T,TH→R,HR→C,HS→R}
(二)由于R中的所有属性均在F中都出现,所以转下一步
(三)对F按具有相同左部的原则分为:
F={CS→G,C→T,TH→R,HR→C,HS→R}
R1=CSG,R2=CT,R3=THR,R4=HRC,R5=HSR
所以 ρ={ R1(CSG), R2(CT), R3(THR), R4(HRC), R5(HSR) }