
【数据库】 关系模式的规范化理论----一文让你轻松理解其中奥秘
文章目录关系模式设计中存在的问题关系的形式化定义数据依赖的基本概念函数依赖非平凡函数依赖、平凡函数依赖完全函数依赖和部分函数依赖传递函数依赖关键字和超关键字数据依赖的公理系统函数依赖的逻辑蕴含Armstrong公理系统函数依赖闭包函数依赖集的等价和覆盖最小函数依赖集候选码的快速求解理论及方法三范式和BCNF范式第一范式(1NF)第二范式(2NF)第三范式(3NF)BCNF范式关系模式的分解及其问题
为什么引入关系数据库的规范化设计?
出现一组数据,如何构造一个适用于这组数据的数据关系模型,这是数据库最基本并且是一个无法回避的问题。(走路要选择路线)对于一个现实的问题,如何选择一个比较好的关系模型集合,主要包括3个方面:数据依赖、范式、和模式设计方法。
关系模式设计中存在的问题
对于一个不好的数据库模型主要有以下三个缺点:
- 冗余度大:只更新记录其中的一个字段,对于其他字段的值只需要复制过来,如果字段多,并且需要更新的字段少,那么这些复制就毫无意义可言。
- 插入异常:如果一个关系表中有两个主键(主键不能为空值),假如说这个关系表中有学生学号和课程号两个主键和其他的属性,如果我只开设的一个课程,那么就会有一个课程号,但是如果没有学生选择这个课程,那这条课程的记录可以插入到这个关系表中吗?—>不能。因此学生学号为空值(没有学生选择这门课)。这样就会产生插入异常(记录没办法放在在这个关系表格中)
- 删除异常:还是利用上面的关系表,如果一门课只要一个学生选(这里的刘强),现在这个学生毕业或者辍学了,那么就需要将该学生选课的信息删除,但是如果利用这个关系模式表格,课程的信息也会随着删除。
因此应该将这个表格分解成一下3个模式:
S(SNO,SNAME,DNAME,AGE)
C(CNO,CNAME,PRE_CNO)
SC(SNO,CNO,SCORE)
也就是形成了如下的三张表格:
关系的形式化定义
关系模式由五部分组成,即他是一个五元组:R(U,D,DOM,F)
R:关系名
U:组成该关系的属性名集合
D:属性组U中的属性所来自的域
DOM:属性向域的映像集合
F:属性间数据的依赖关系集合
对数据库设计影响重大的是U和F,因此关系模式通常被简化为三元组:R(U,F)
数据依赖的基本概念
函数依赖
对于一个关系模型R(U),U是关系R的属性集合。X和Y是U的两个子集。对于R中的任意的两个元组,它们在X上的属性值相同,在Y上的属性值也相同。那么就称“X函数确定Y”或者“Y函数依赖于X”。记作X->Y
举例:例如说上面的关系模式,一个学生记录,如果学号固定下来,那么该学生的姓名、专业、年龄也就随之固定下来。因此可以记作为SNO->SNAME、SNO->DNAME、SNO->AGE;同时对于定义而言,X和Y是属性全集的一个子集,也就是说X和Y不一定只有一个属性。比如说这里的学生和课程确定下来,那么该学生本课程的成绩也就确定下来,即:(SNO,CNO)->SCORE
非平凡函数依赖、平凡函数依赖
函数依赖X->Y如果满足Y⊈X,则称此函数依赖为非平凡函数依赖;否则Y⊆X,X->Y很显然成立,任意两个元组的X属性集都是相等的,Y属性集包含于X属性集,Y属性集的值自然都是相等的。此种称为平凡函数依赖。例如X->∅、X->X、XZ->X。
完全函数依赖和部分函数依赖
在关系R(U)中如果有函数依赖X->Y,对于任意的X的真子集X‘,都有X’!->Y,那么就称Y完全依赖于X,记作X → f \xrightarrow{f} fY;否则就称为部分函数依赖,记作X → p \xrightarrow{p} pY。
举例:通过{学生学号, 选修课程名}可以得到{该生本门选修课程的成绩},而通过单独的{学生学号}或者单独的{选修课程名}都无法得到该成绩,则说明{该生本门选修课程的成绩}完全依赖于{学生学号,选修课程名}
通过{学生学号,课程号}可以得到{该生姓名},而通过单独的{学生学号}已经能够得到{该生姓名},则说明{该生姓名}部分依赖于{学生学号,课程号}; 又比如, 通过{学生学号,课程号}可以得到{课程名称},而通过单独的{课程号}已经能够得到{课程名称},则说明{课程名称}部分依赖于{学生学号,课程号}。(部分依赖会造成数据冗余及各种异常。)
传递函数依赖
设X、Y、Z是关系模式R(U)的不同的属性集,如果X->Y,Y → / \xrightarrow{/} /X(X不依赖于Y),Y->Z。那么我们就称Z传递依赖于X。否则成为非传递函数依赖。比如说这样一个属性集(学号、系名、系主任)。学号->系名;系名->系主任;但同时系名 → / \xrightarrow{/} /学号;这样我们就称系主任传递依赖于学号。
关键字和超关键字
这里的关键字其实就是我们常说的候选码,候选码是确定下来,这个元组就随之确定下来。顺着这句话的意思我们就可以总结出关键字的 定义:在关系模式R(U)中,若K⊆U,且满足K → f \xrightarrow{f} fU,就称K是关系R的关键字。这里K可以是某个具体的属性也可以是一个属性集合。而我们常说的主键其实就是选择其中一个候选码为主键。
超关键字:对于一个属性集合这个属性集合既包含了关键字属性集合,又包含了非关键字属性集合,那么这个属性集合就叫超关键字
比如说学号 → f \xrightarrow{f} f(姓名,年龄,专业,宿舍号),但是(学号,姓名) → p \xrightarrow{p} p(年龄,专业,宿舍号)。这里的(学号,姓名)就是一个超关键字。
数据依赖的公理系统
函数依赖的逻辑蕴含
设F是关系模式R(U)上的一个函数依赖集, X →Y不包含在F中,但是如果可以从F中推导出X →Y,则称称F逻辑蕴含X →Y。表示为F⊨X->Y。当然如果X->Y包含在F中,F也是逻辑蕴含X->Y的。
Armstrong公理系统
F是关系模式R(U)上的一个函数依赖集
三条基本推理规则:
A1. 自反律(平凡的函数依赖):
若Y⊆X⊆U,则X →Y为F所蕴含
A2. 增广律(扩展律):
若X→Y为F所蕴含,且Z⊆U,则XZ→YZ为F所蕴含。
A3. 传递律:
若X→Y及Y→Z为F所蕴含,则X→Z为F所蕴含。X → \rightarrow →Y&&Y → \rightarrow →Z=>X → \rightarrow →Z
根据A1,A2,A3这三条推理规则可以得到下面三条推论:
- 合并规则:由X→Y,X→Z,有X→YZ。 证明:X->Y => XX->XY => X->XY ; X->Z => XY->YZ ∴X->YZ
- 伪传递规则:由X→Y,WY→Z,有XW→Z。证明:X->Y => XW->YW ; YW=>Z ∴ XW->Z
- 分解规则:由X→Y及 Z⊆Y,有X→Z。证明:∵Z⊆Y ∴Y->Z 又∵X->Y ∴ X->Z
设有关系模式R(A,B,C,D,E)以及其上的函数依赖集F={AB→DE,A →B, E→C},求证F必蕴涵A→C
函数依赖闭包
若F为关系模式R(U)的函数依赖集,我们把F以及所有被F逻辑蕴涵的函数依赖的集合称为F的闭包,记作F+。
定义: 设关系模式R(U,F ),U 为其属性集,F 为其函数依赖集,则称在所有用Armstrong 公理从F 推出的函数依赖X → Ai 中,Ai 的属性集合为X 的属性闭包。也就是说,属性集X关于函数依赖集合的闭包,里面的元素是属性(而不是函数依赖),这些属性是F根据Armstrong 公理推导出来的。
F的闭包举例F={X→Y,Y → Z}, 求F+.
F+={
X → φ, Y → φ, XY → φ,自反律 XZ → φ, YZ → φ, XYZ → φ, 自反律
X → X, Y → Y, XY → X, 自反律 XZ → X, YZ → Y, XYZ → X,自反律
X → Y, Y → Z , XY → Y,扩展律 XZ → Y扩展律+自反律, YZ → Z, 自反律 XYZ → Y,自反律
X → Z传递律, Y → YZ, XY → Z, XZ → Z, YZ → YZ, XYZ → Z,
X → XY, Z → φ, XY → XY, XZ → XY, XYZ → XY,
X → XZ, Z → Z, XY → YZ, XZ → XZ, XYZ → YZ
X → YZ, XY → XZ, XZ → XY, XYZ → XZ,
X → ZYZ, XY → XYZ, XZ → XYZ, XYZ → XYZ }
每一条都可以使用Armstrong公理的6条定理推导出来。
设F为属性集U上的一组函数依赖,X,Y⊆U,X→Y能由F 根据Armstrong公理导出的充分必要条件是Y ⊆XF+
这一条定理的用途:将判定X→Y是否能由F根据Armstrong公理导出问题,就转化为求出XF+ ,判定Y是否为XF+的子集的问题。
求属性闭包的算法
求属性集X(X U)关于U上的函数依
赖集F 的闭包XF+
输入:X,F
输出:XF+
步骤:
1)令X(0)=X,i=0
2)求B,这里B = { A |(∃V)(∃W)(V→W⊆F∧V⊆X(i)∧A⊆W)};看Result中的属性根据F中的关系还能推出哪些属性
3)X(i+1)=B∪X(i)再把这些属性加入Result中
4)判断是否存在以下情况:
X(i)=U 如果X的属性闭包已经和U相等了,就不需要再去找属性(U:我全都给你了,我这儿没有你没用过的属性了;X:嗯不错)
X(i+1)=X(i) 如果连续两次循环求得的属性集都是相同的,那么就没必要继续往下循环
在F中未用过的函数依赖的左边再也找不到x(i)的子集 利用当前属性集中的属性利用F中的依赖关系找不到新的属性
若存在,则算法终止。
否则, i=i+l,返回第(2)步。
简单理解:假设属性集是U,U上的函数依赖集是F。假设要求属性A的闭包Result
1,在F中找出所以依赖与A的属性,然后把这这些直接依赖于A的属性加入到Result中
2,看Result中的属性根据F中的关系还能推出哪些属性,再把这些属性加入Result中
3,重复步骤1,2。直到全部找完,所得的Result就是A的闭包。
举例:已知关系模式R<U,F>,其中
U={A,B,C,D,E};
F={AB→C,B→D,C→E,EC→B,AC→B}。
求(AB)F+ 。
解: 设X(0)=AB;
(1)计算X(1): 逐一的扫描F集合中各个函数依赖,
找左部为A,B或AB的函数依赖。得到两个:
AB→C,B→D。
于是X(1)=AB∪CD=ABCD。
(2)因为X(0)≠ X(1) ,所以再找出左部为ABCD子集的那些函数依赖,又得到AB→C,B→D, C→E,AC→B,
于是X(2)=X(1)∪BCDE=ABCDE。
(3)因为X(2)=U,算法终止
所以(AB)F+=ABCDE。
函数依赖集的等价和覆盖
设F和G是关系R(U)上的两个依赖集,如果G+=F+,就说函数依赖集F与G等价。记为F=G。也可以称F覆盖G或者G覆盖F或者FG相互覆盖。
G+=F+充分必要条件是F⊆G+, G⊆F+
检查两个函数依赖集F和G是否等价的方法:
1)检查F中每个函数依赖是否属于G+,如果全部满足,则F⊆G+.例如:若有X->Y∈F,就计算XG+;如果Y∈XG+,那么X->Y∈G+
2)同第一步检查G⊆F+
3)如果F⊆G+且G⊆F+,那么F与G等价
最小函数依赖集
如果函数依赖集F满足下列条件,则称F为一个极小函数依赖集,亦称为最小依赖集或最小覆盖。
(1)、F中任一函数依赖右部仅含有一个属性。
(2)、F中不存在这样的函数依赖 X→A,使得F与F-{X→A} 等价。
(3)、F中不存在这样的函数依赖X→A,X有真子集Z使得F-{X→A}⋃{Z→A} 与F等价。
Translate:
1、F中任一函数依赖的右边只有一个属性。
2、F中不存在这样的函数依赖:从现有的函数依赖集中删除一个函数依赖X$ \rightarrow$A,删除后所得的函数依赖集与原来的函数依赖集等价,这样的函数依赖是不允许存在的。
3、F中不存在这样的函数依赖:假设函数依赖集中存在AB→Y,现对该依赖的左部进行化简,即删除A,得B→ Y;或删除B,得A→ Y,若经过化简后的函数依赖集与没有化简前的函数依赖集等价,那么这样的函数依赖是不允许存在的。
求最小依赖集的方法:
1、首先,先利用函数依赖的分解性,将函数依赖集中右部不为单个属性的分解为单属性。
2、对于经过第1步筛选后的函数依赖集F中的每一个函数依赖X→A,进行以下操作:
2.1、将X→A从函数依赖中剔除
2.2、基于剔除后的函数依赖,计算属性X的闭包,看其是否包含了A,若是,则该函数依赖是多余的(这里体现出前面说的等价,因为如果基于化简后的函数依赖依赖,计算X的闭包依然包含A,则说明A可以由其他依赖推出,X→A不是必须的),可以删除,否则不能删除
3、对于经过第2步筛选后的函数依赖集F中每个左部不为单个属性的函数依赖AB→Y,进行以下操作:
我们约定,经过第二步筛选后的函数依赖集记为F1,经过第三步处理后的函数依赖集为F2。
3.1、去除A,得B→Y,得F2,基于F1和F2计算属性B的闭包,如果二者相等,则说明它们是等价的,A可以去除;如果不相等,则A不能去除。
3.2、去除B,得A→ Y,得F2,基于F1和F2计算属性A的闭包,如果二者相等则说明它们是等价的,B可以去除;如果不相等,则B不能去除。
举例
关系模式R(U,F)中,U={A,B,C,D,E,G},F={B→D,DG→C,BD→ E,AG→B,ADG→BC};求F的最小函数依赖集。
解:
1、首先根据函数依赖的分解性,对F进行第一次筛选,需要变动的有:
ADG→BC拆解成ADG→B、ADG→C
得新函数依赖集:
F = {B→ D,DG→C,BD→E,AG→ B,ADG→ B,ADG→C}
2、筛选多余的函数依赖
- 2.1:去除B→D,得F = {DG→ C,BD→E,AG→B,ADG→B,ADG→ C},BF+ = {B},不包含D,故B→D不删除。
- 2.2:去除DG→C,得F = {B→ D,BD→E,AG→B,ADG→ B,ADG→C},(DG)F+ ={D,G},不包含C,故DG→ 不删除。
- 2.3:去除BD→ E,得F = {B→D,DG→C,AG→ B,ADG→B,ADG→C},(BD)F+ = {B,D},不包含E,故BD→不删除。
- 2.4:去除AG→B,得F = {B→D,DG→C,BD→E,ADG→B,ADG→C},(AG)F+= {A,G},不包含B,故AG→B不删除。
- 2.5:去除ADG→B,得F = {B→ D,DG→C,BD→E,AG→B,ADG→C},(ADG)F+ = {A,D,G,C,B,E},包含B,故ADG→B去除。
- 2.6:去除ADG→C,得F = {B→D,DG→C,BD→E,AG→ B},(ADG)F+ = {A,D,G,C,B,E},包含C,故ADG→C去除。
经过第二部筛选后,函数依赖集F变为{B→D,DG→C,BD→E,AG→ B}。
3、化简函数依赖左侧不为单个属性的函数依赖
-
3.1:先看DG→C
-
3.1.1:去除D,得G→C,得函数依赖集F1 = {B→D,G→ C,BD→ E,AG→B}。
基于F1,可求得GF+= {G,C}。
基于F(第二步求出的,下同),可求得GF+= {G}
可见二者并不相同,所以D不去除。 -
3.1.2:去除G,得D→C,得函数依赖集F1 = {B→D,D→ C,BD→E,AG→B}
基于F1,可求得DF+= {D,C}
基于F,可求得DF+={D}
可见二者并不相同,所以G不去除。 -
综上,DG→C,已是最简。
-
-
3.2:再看BD→E
- 3.2.1:去除B,得D→E,得函数依赖集F1 = {B→D,DG→C,D→ E,AG→B}
基于F1,可求得DF+= {D,E}
基于F,可求得DF+= {D}
可见二者并不相同,所以B不去除。 - 3.2.2:去除D,得B→E,得函数依赖集F1 = {B→D,DG→C,B→E,AG→B}
基于F1,可求得BF+= {B,E,D}
基于F,可求得BF+= {B,D,E}
可见二者相同,所以D可以去除。 - 综上,BD→E,可化简为B→E。
- 3.2.1:去除B,得D→E,得函数依赖集F1 = {B→D,DG→C,D→ E,AG→B}
-
3.3:最后看AG→B
-
3.3.1:去除A,得G→B,得函数依赖集F1 = {B→D,DG→C,B→E,G→B}
基于F1,可求得GF+= {G,B}
基于F,可求得 GF+= {G}
可见二者并不相同,所以A不可去除。 -
3.3.2:去除G,得A→B,得函数依赖F1 = {B→D,DG→C,B→E,A→B}
基于F1,可求得AF+= {A,B}
基于F,可求得AF+= {A}
可见二者并不相同,所以G不可去除。 -
综上,AG→B,已是最简。
综上,R的最小函数依赖集为F = {B→D,DG→C,B→E,AG→B}
-
如果求解过程中就删除了某个函数依赖,进行到下一步的时候函数依赖集就是删掉上一个函数依赖之后的函数依赖集
例子参考:(14条消息) 数据库建模和设计(2):函数依赖、闭包、最小函数依赖集、范式、模式分解_prdslf001001的博客-CSDN博客_函数依赖的闭包
最小依赖集不是唯一的
F = {A→B,B→A,B→C,A→C,C→A}
F的最小依赖集:
Fm1= {A→B,B→C,C→A}
Fm2= {A→B,B→A,A→C,C→A}
Fm1求解过程:
但是如果第二步是去掉B->C的话就会得到Fm2
产生不唯一的原因:求解过程中对于各属性的处置顺序不同。
候选码的快速求解理论及方法
谈快速求解肯定就有一般的笨方法
1.一般求解方法(使用于属性较少的表)
主要方法:由少到多找出每个属性集的闭包,如果其属性集的闭包包含全部的属性集,那么这个属性集就是要求的候选码。
例子:
假设:R(U),U={A,B,C,D}
F={AB->C,C->D,D->A},找出R的所有候选键。
方法:找出U中每个集合的闭包。
单属性集:
A+={A} B+={B} C+={C,D,A} D+={D,A}
二属性集:
(AB)+={A,B,C,D}
(AC)+={A,C,D}
(AD)+={A,D}
(BC)+={B,C,D,A}
(BD)+={B,D,A,C}
(CD)+={C,D,A}
可以看出AB和BC、BD的闭包为包含全部的属性集,所以这是三个为本例子的候选键。
由于候选键除其本身的任一子集的闭包都不能包含全部的集合,所以不用考虑包含候选键的属性集的闭包了。
比如ABC包含AB,AB是候选键,所以ABC不能是候选键,同理ABD。
所以三个属性的集合:(ACD)+={A,C,D},不符合要求
因为四个属性的集合已经包含有候选键,所以不考虑。
最终得出候选键为:AB、BC、BD
快速求解方法:
(1)求最小函数依赖集Fmin
(2)根据Fmin,将给定的关系R的属性分为4类:
- L类 仅出现在函数依赖左边的属性
- R类 仅出现在函数依赖右边的属性
- N类 在F的函数依赖左右两边均未出现的属性
- LR类 在F的函数依赖左右两边均出现的属性
(3)求闭包
如果X是N类和L类组成的属性集,且X+包含了R的全部属性,则X是R的惟一候选码,否则再从LR类属性中依次取一个、两个………加入X中,并求其闭包,直到闭包包含全部属性。
规则:
1、若X是L类属性,则X必为R的任一候选码的成员
2、若X是R类属性,则X不在任何候选码中
3、若X是R的N类属性,则X必包含在R的任一候选码中
设有关系模式R(A,B,C,D),其函数依赖集F={D → \rightarrow →B,B → \rightarrow →D,AD → \rightarrow →B,AC → \rightarrow →D},求R的所有候选码。
求得Fmin={D → \rightarrow →B,B → \rightarrow →D,AC → \rightarrow →D}
L类:ac R类:无 N类:无 LR类:bd
(ac)+=(abcd)包含了R的全部属性,那么这里的ac就是我们所要求得的候选码
设有关系模式R(A,B,C,D,E,G,P),其函数依赖集F={A → \rightarrow →D,E → \rightarrow →D,BC → \rightarrow →D,DC → \rightarrow →A},求R的所有候选码。
Fmin={A → \rightarrow →D,E → \rightarrow →D,BC → \rightarrow →D,DC → \rightarrow →A}
L类:BCE R类:无 N类:GP LR类:AD
(BCEGP)+=(ABCDEGP)包含了R的全部属性,这里的BCEGP就是我们所要求得的候选码
左边全部为单属性的函数依赖集的候选码成员的图论判定方法。
举例:假设R={O,B,I,S,Q,D},F={S→D,D →S,I →B,B →I,B →O,O →B},求R的所有候选码。
首先利用上面的快速求解方法求R的所有候选码
对于F={S→D,D →S,I →B,B →I,B →O,O →B}经过计算(这里求最小函数依赖集的过程就不过多赘述)
Fmin={S→D,D →S,I →B,B →I,B →O,O →B}
L类:无 R类:无 N类:Q LR类:SDIBO
(Q)+=∅
(QS)+=QSD≠U(U是R的全部属性集)
(QD)+=QSD≠U
(QI)+=QIB≠U
(QB)+=QBI≠U
(QO)+=QOB≠U
(QSD)+=QSD≠U
(QSI)+=QSIBOD=U √
(QSB)+=QSBDIO=U √
(QSO)+=QSOBDI=U √
(QDI)+=QDISBO=U √
(QDB)+=QDBOIS=U √
(QDO)+=QDOSBI=U √
(QIB)+=QIB≠U
(QIO)+=QIOB≠U
(QBO)+=QBO≠U
∴综上候选码为:QSI、QSB、QSO、QDI、QDB、QDO
但是对于左边全是单属性的函数依赖集,我们有以下的这种图论做法:
(1)求F的最小函数依赖集Fmin
(2)构造函数依赖图
(3)从图中找出关键属性集X(即N,L类属性)
(4)查看图中有无独立回路,若无,则输出X为唯一候选码。若有,则从各个独立回路中各取一个结点与X组合成一个候选码。取尽所有可能的组合,则可以得到R的全部候选码。
候选码的个数等于各独立回路中结点个数的乘积。每个候选码所含属性个数等于关键属性个数X加上独立回路个数。
三范式和BCNF范式
构造数据库必须遵循一定的规则。在关系数据库中,这个规则就是范式。关系数据库中的关系必须满足一定的要求,即满足不同的范式。
第一范式(1NF)
任何一个关系数据库里,1NF是对关系模式的基本要求,不满足1NF的数据库就不是关系数据库。 对于一个实体,它的属性不能有多个值或者不能有重复的属性。意思就是1NF就是无重复的列,并且每个属性列不能再分。
下表就不符合1NF的要求
因此应该设计成这样:
但是符合1NF的设计仍然会出现数据冗余过大、插入异常、修改异常的问题,例如下表:
-
每一名学生的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次——数据冗余过大
-
假如学校新建了一个系,但是暂时还没有招收任何学生(比如3月份就新建了,但要等到8月份才招生),那么是无法将系名与系主任的数据单独地添加到数据表中去的 (注1)——插入异常
-
注1:根据三种关系完整性约束中实体完整性(注2)的要求,关系中的码(注3)所包含的任意一个属性都不能为空,所有属性的组合也不能重复。为了满足此要求,图中的表,只能将学号与课名的组合作为码,否则就无法唯一地区分每一条记录。
-
注2:关系完整性约束:实体完整性(关系主属性不能取空值)、参照完整性(在关系模型中实体与实体间的联系都是用关系来描述的,自然存在着关系与关系间的引用)、用户定义的完整性(应用领域需要遵循的约束条件,体现了具体领域中的语义约束)
-
注3:码、候选码、主属性、非主属性、主码的区别:(这里对于概念的理解确实困扰我好久)
能唯一确定元组的属性或者属性组称为超键,超键就是码;
在满足超码条件的基础上(能唯一确定元组的属性或者属性组),其任何真子集都不能唯一确定元组的值,那么我们就称这样的属性或者属性组为候选码(键);
主属性是所有候选码的并集,包含所有的候选码;
非主属性就是属性集去掉主属性后的属性;
主码(主码)就是从候选码里选择一条作为一个或者一组唯一并且不能为空值的属性或者属性组;
-
-
假如将某个系中所有学生相关的记录都删除,那么所有系与系主任的数据也就随之消失了(一个系所有学生都没有了,并不表示这个系就没有了)。——删除异常
-
假如李小明转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据。——修改异常。
-
---------->问题这么多1NF已经解决不了,请看2NF!
第二范式(2NF)
判断的依据实际上就是看数据表中是否存在非主属性对于码的部分函数依赖。若存在,则数据表最高只符合1NF的要求,若不存在,则符合2NF的要求。
2NF消除了非主属性对于码的部分函数依赖
还是以此表为例
对于2NF的判断方法如下:
第一步:找出数据表中所有的候选码。
第二步:根据第一步所得到的候选码,找出所有的主属性(候选码)。
第三步:数据表中,除去所有的主属性,剩下的就都是非主属性了。
第四步:查看是否存在非主属性对码的部分函数依赖。
对于上表的处理:
第一步我们可以找到的候选码是学号和课名,即主属性就是学号和课名,非主属性是姓名、系名、系主任、分数
函数依赖关系如下图所示:
对于(学号,课名) → 姓名,有 学号 → 姓名,存在非主属性 姓名 对码(学号,课名)的部分函数依赖。
对于(学号,课名) → 系名,有 学号 → 系名,存在非主属性 系名 对码(学号,课名)的部分函数依赖。
对于(学号,课名) → 系主任,有 学号 → 系主任,存在非主属性 对码(学号,课名)的部分函数依赖。
所以表存在非主属性对于码的部分函数依赖,最高只符合1NF的要求,不符合2NF的要求。
为了让表符合2NF的要求,我们必须消除这些部分函数依赖,只有一个办法,就是将大数据表拆分成两个或者更多个更小的数据表,在拆分的过程中,要达到更高一级范式的要求,这个过程叫做”模式分解“(下一节)。模式分解的方法不是唯一的,以下是其中一种方法:
选课(学号,课名,分数)
学生(学号,姓名,系名,系主任)
对于选课表,其码是(学号,课名),主属性是学号和课名,非主属性是分数,学号确定,并不能唯一确定分数,课名确定,也不能唯一确定分数,所以不存在非主属性分数对于码 (学号,课名)的部分函数依赖,所以此表符合2NF的要求。
对于学生表,其码是学号,主属性是学号,非主属性是姓名、系名和系主任,因为码只有一个属性,所以不可能存在非主属性对于码 的部分函数依赖,所以此表符合2NF的要求
对于模式分解之后的函数依赖关系如下图所示:
分解成的小表就如下图所示:
现在我们开始这两张表进行分析,
- 李小明转系到法律系
只需要修改一次李小明对应的系的值即可。——有改进 - 数据冗余是否减少了?
学生的姓名、系名与系主任,不再像之前一样重复那么多次了。——有改进 - 删除某个系中所有的学生记录
该系的信息仍然全部丢失。——无改进 - 插入一个尚无学生的新系的信息。
因为学生表的候选码是学号,不能为空,所以此操作不被允许。——无改进
还有问题---->引进3NF
第三范式(3NF)
3NF在2NF的基础上消除了非主属性对码的传递函数依赖
满足第三范式的数据库表应该不存在如下依赖关系:
关键字段 → 非关键字段x → 非关键字段y
举例:
假定学生关系表为Student(学号,姓名,年龄,所在学院,学院地点,学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
(学号) → (姓名,年龄,所在学院,学院地点,学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
(学号) → (所在学院) → (学院地点,学院电话)
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
把学生关系表分为如下两个表:
学生:(学号,姓名,年龄,所在学院);
学院:(学院,地点,电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
我们继续分析这张表:
经过我们的分析这张表还是有问题的,那它是否符合3NF的要求?
对于选课表,主码为(学号,课名),主属性为学号和课名,非主属性只有一个—分数,不可能存在传递函数依赖,所以选课表的设计,符合3NF的要求。
对于学生表,主码为学号,主属性为学号,非主属性为姓名、系名和系主任。因为 学号 → 系名,同时 系名 → 系主任,所以存在非主属性系主任对于码学号的传递函数依赖,所以学生表的设计,不符合3NF的要求。
为了让数据表设计达到3NF,我们必须进一步进行模式分解为以下形式:
选课(学号,课名,分数)
学生(学号,姓名,系名)
系(系名,系主任)
对于选课表,符合3NF的要求,之前已经分析过了。
对于学生表,码为学号,主属性为学号,非主属性为系名,不可能存在非主属性对于码的传递函数依赖,所以符合3NF的要求。
对于系表,码为系名,主属性为系名,非主属性为系主任,不可能存在非主属性对于码的传递函数依赖(至少要有三个属性才可能存在传递函数依赖关系),所以符合3NF的要求。
新产生的函数依赖关系图如下图:
经过模式分解产生的数据表就如下图所示:
对此表进行分析还有问题吗?
- 删除某个系中所有的学生记录
该系的信息不会丢失。——有改进 - 插入一个尚无学生的新系的信息。
因为系表与学生表目前是独立的两张表,所以不影响。——有改进 - 数据冗余更加少了。——有改进
由此可见,符合3NF要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。当然,在实际中,往往为了性能上或者应对扩展的需要,经常 做到2NF或者1NF,但是作为数据库设计人员,至少应该知道,3NF的要求是怎样的。
BCNF范式
在 3NF 的基础上消除主属性对于码的部分与传递函数依赖。
在3NF中的函数依赖集中只有这样的函数依赖(对于X → \rightarrow →Y,X一定含有码,候选码⊆码,意思就是X中一定要有候选码,任意一个都行)
若:
某公司有若干个仓库;每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作;
一个仓库中可以存放多种物品,一种物品也可以存放在不同的仓库中。每种物品在每个仓库中都有对应的数量。
那么关系模式 仓库(仓库名,管理员,物品名,数量) 属于哪一级范式?
答:已知函数依赖集:仓库名 → 管理员,管理员 → 仓库名,(仓库名,物品名)→ 数量
码:(管理员,物品名),(仓库名,物品名)
主属性:仓库名、管理员、物品名非主属性:数量
∵ 不存在非主属性对码的部分函数依赖和传递函数依赖。
∴ 此关系模式属于3NF。
基于此关系模式的关系(具体的数据)可能如图所示:
好,既然此关系模式已经属于了 3NF,那么这个关系模式是否存在问题呢?我们来看以下几种操作:
先新增加一个仓库,但尚未存放任何物品,是否可以为该仓库指派管理员?——不可以,因为物品名也是主属性,根据实体完整性的要求,主属性不能为空。
某仓库被清空后,需要删除所有与这个仓库相关的物品存放记录,会带来什么问题?——仓库本身与管理员的信息也被随之删除了。
如果某仓库更换了管理员,会带来什么问题?——这个仓库有几条物品存放记录,就要修改多少次管理员信息。
从这里我们可以得出结论,在某些特殊情况下,即使关系模式符合 3NF 的要求,仍然存在着插入异常,修改异常与删除异常的问题,仍然不是 ”好“ 的设计。
造成此问题的原因:存在着主属性对于码的部分函数依赖与传递函数依赖。(在此例中就是存在主属性【仓库名】对于码【(管理员,物品名)】的部分函数依赖。
解决办法就是要在 3NF 的基础上消除主属性对于码的部分与传递函数依赖。
仓库(仓库名,管理员)
库存(仓库名,物品名,数量)
这样,之前的插入异常,修改异常与删除异常的问题就被解决了。
以上就是关于 BCNF 的解释。
多值依赖、第四范式、第五范式
在讲这一部分的知识点之前,先引入一张表。学校中某一门课程由多个教师讲授,他们使用相同的一套参考书。关系模式Teaching(C, T, B); 课程C、教师T 和 参考书B
转换成二维表格:
关系模式的分析:首先这个关系模式∈1NF;接着确定本关系模式的候选码,发现(C,T,B)为候选码,非主属性为∅,非主属性对码都是完全函数依赖的。所以这个关系模式∈2NF;由于非主属性为∅,所以这个关系模式∈3NF;不存在主属性C、T、B对(C,T,B)这个候选码完全函数依赖和传递函数依赖,因此此关系模式∈BCNF。
经过我们的分析发现此关系模式已经达到了BCNF的地步,似乎已经达到了很完美的境界了。但是我们仔细分析会发现依然存在问题:
- 数据冗余度大:当有多名任课教师的时候,参考书就需要存储多次(这些存储是无意义的,只需要一个就够了)
- 插入数据复杂:当某一课程增加一名任课教师时,该课程有多少本参考书,就必须插入多少个元组
例如物理课增加一名教师刘关,需要插入两个元组:(物理,刘关,普通物理学) 和(物理,刘关,光学原理) - 删除操作复杂: 某一门课要去掉一本参考书,该课程有多少名教师,就必须删除多少个元组
- 修改操作复杂:某一门课要修改一本参考书,该课程有多少名教师,就必须修改多少个元组
产生原因:该关系模式里存在多值依赖
多值依赖
设R(U)是一个属性集U上的一个关系模式, X、 Y和Z是U的子集,并且Z=U-X-Y,多值依赖 X→→Y成立当且仅当对R的任一关系r,r在(X,Z)上的每个值对应一组Y的值,这组值仅仅决定于X值而与Z值无关。
看到这个你可能就会觉得我说的这几行都是废话。没错!“你他娘的真是个人才!”就是废话。大白话就是说一个关系模式的所有属性被分为3组,X、Y、Z,多值依赖X → \rightarrow → → \rightarrow →Y成立的条件是什么呢?对于X每一个值都对应一组(注意是一组不是一个,如果是单个的话就不是多值了,就是函数依赖了)Y,不论另一个属性Z取什么。
拿我们上面的表格来说,对于C的一个值,假设C的值为物理,会对应T的值为李永和王军,不论B的值是什么。
平凡多值依赖和非平凡多值依赖
若X→→Y,而Z=φ,则称X→→Y为平凡的多值依赖; 否则称X→→Y为非平凡的多值依赖
第四范式
关系模式R<U,F>∈1NF,如果对于R的每个非平凡多值依赖X→→Y(Y 不属于X),X都含有候选码,则R∈4NF。
- 如果是平凡多值依赖R∈4NF
- 第4NF中所允许的非平凡多值依赖实际上就是函数依赖(X→Y)
- 如果R ∈ 4NF, 则R ∈ BCNF
还是拿我们刚才的表格来看,它的关系模式∈4NF吗?
答案:不属于
因为存在非平凡的多值依赖C → \rightarrow → → \rightarrow →T且C不是候选码。候选码是(C,T,B)
用投影分解法把Teach分解为如下两个关系模式:
CT(C, T) ∈ 4NF
CB(C, B) ∈ 4NF
C→→T, C→→B是平凡多值依赖
第五范式
连接依赖:设U是关系模式R的属性全集。R1、R2、……Rn是U的子集并且满足U=R1∪R2∪……∪Rn,ρ={R1,R2,……,Rn}是R的一个分解。如果对于R的每一个关系r都满足r= ∏R1(r) ∏R2(r) ∏…… ∏Rn(r),那么成为连接依赖。记为*(R1,R2,……,Rn)
那么关于第五范式就是在关系模式中,除了超键构成的连接依赖外,别无其他的连接依赖,那么此关系模式就是第五范式。
所以的依赖关系都依赖于超键(包含候选码的属性)
关系模式的分解及其问题
关系模式的分解思维引入
按照用户需求提升当前关系模式的范式等级,才会使得我们当前使用的关系模式数据表更加耐用。
那么如何对关系模式进行“升级”?----->关系模式的分解
前提要点:1.把低一级的关系模式分解为若干个高一级的关系模式的方法不是唯一的;2.只有能够保证分解后的关系模式与原关系模式等价,分解方法才有意义。
拆二维表~~~~~~~(o( ̄ヘ ̄o#))
从函数依赖的角度来看,关系模式规范化的基本思路:
- 从非主属性到主属性逐步消除决定因素不是候选码的非平凡函数依赖,从而使每个决定因素都包含候选码,而不是候选码的一部分。意思就是逐渐集中决定因素是包含候选码,如果是候选码的一部分的话,该决定因素就不能区别元组间所有属性的值。
- 第二、第三范式只检查非主属性和候选码之间的函数依赖关系,分别消除了非主属性对码的部分函数依赖和传递函数依赖。
- BCNF范式检查主属性对码的部分函数依赖和传递函数依赖。
那么如何进行规范化?
规范化的基本思想:
- 消除不合适的数据依赖,如部分函数依赖、传递函数依赖、非平凡的多值依赖等。
- 采用“一事一地”的原则: 让一个关系只描述一个概念。若多于一个概念就把它“分离”出去,实际上就是对概念进行单一化的过程。学生表就只描述学生这个实体,里面不要插入课程的概念;课程表只需要描述课程的概念属性,不需要加入学生的概念属性。一张表里既有学生又有课程,这张表肯定有问题。
- 在设计数据库模式结构时,必须对现实世界的实际情况和用户需求作进一步分析,确定一个合适的、能够反映现实世界的关系模式。(说白了就是要实事求是,基于现实)
- 并不是规范化程度越高越好,规范化步骤可以在其中任何一步终止。(符合用户需求即可)
对于关系模式的分解通常用无损连接性和函数依赖保持性进行衡量。
该怎么解释这两个标准呢?
---->无损连接性:在分解之后,n个分解关系通过自然连接(自然连接是在等值连接的基础上去掉相同的列,如果自然连接中找不到等值信息<相同的列>那么这种自然连接就等价于笛卡尔积)形成的二维表和没分解之前的关系的二维表是等价的。(元组没有增加也没有减少),则称这种分解形成的关系模式保持无损连接性;----->如何判断无损连接性:保持函数依赖性---->若分解之后的关系模式中仍然存在和没分解之前属性的函数依赖关系则称保持分解的函数依赖性.
模式分解的三种标准:
⒈ 分解具有无损连接性
⒉ 分解要保持函数依赖
⒊ 分解既要保持函数依赖,又要具有无损连接性
无损连接性和分解保持函数依赖是两个互相独立的标准。具有无损连接性的分解不一定能够保持函数依赖。同样,保持函数依赖的分解也不一定具有无损连接性。
(1)如果仅要求分解具有无损连接性,则模式分解一定能达到4NF
(2)如果仅要求分解保持函数依赖,则模式分解一定能达到3NF,但不一定能够达到BCNF
(3)如果要求分解既有无损连接性,又保持函数依赖,则一定能达到3NF,但不一定能达到BCNF
分解的无损连接性
对于一分为二的简单分解,有一个十分便捷的验证条件:如果R的分解为ρ={R1,R2},F为R所满足的函数依赖集合,则分解ρ具有无损连接性的充分必要条件为: R1∩R2→(R1-R2)(1)或 R1∩R2→(R2-R1)(2)(PS:1和2满足一个即可)例如:学生关系S ( Sno,Sname, Ssex, Dept, DeptManager )分解为S(Sno,Sname, Ssex, Sdept) 和D(Dept,DeptManager), D∩S = Dept , D-S = DeptManager, Dept→DeptManager为原关系中的函数依赖,此分解为无损连接的分解。
但是如果分解超过两个关系,就需要构造一个测试表进行测试。
通用算法:
无损分解的测试方法。①输入:关系模式R=(A1,A2…An),F是R上成立的函数依赖集,ρ={R1,R2…Rn}是R的一个分解;②输出:判断ρ相对于F是否具有无损分解特性。
(1)建立一张n列k行的表,每一列对应一个属性Aj(1≤j≤n),每一行对应分解中的一个关系模式Ri(1≤i≤k)。若属性Aj在Ri中,则在j列i行交叉处填上aj,否则填上bij.
(2)把表格看成模式R的一个关系,反复检查F中每个FD在表格中是否成立,若不成立,则修改表格中的值,修改方法为:对于F中一个函数依赖X→Y,如果表格中有两行在X值上相等,在Y值上不相等,那么把这两行在Y值上也改成相等的值,如果Y值中一个是aj,那么另一个也改成aj;如果没有aj那么用其中一个bij替换另一个字(尽量把下表ij改成较小的数)。一直到表格不能修改为止,这个过程成为chase(追踪)过程。
(3)若修改后的最后一直表格中**有一行全是a,**即a1,a2…an,则称ρ相对于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),判断这个分解是否具有无损连接性。
第一步:构造测试表:
第二步:对于函数依赖集F中的每一个函数依赖,修改测试表
-
根据A→C,对上表进行处理,由于属性列A上第1、2、5行相同均为a1,所以将属性列C上的b13、b23、b53改为同一个符号b13(取行号最小值)。
-
根据B→C,对上表进行处理,由于属性列B上第2、3行相同均为a2,所以将属性列C上的b13、b33改为同一个符号b13(取行号最小值)。
-
根据C→D,对上表进行处理,由于属性列C上第1、2、3、5行相同均为b13,所以将属性列D上的值均改为同一个符号a4。
-
根据DE→C,对上表进行处理,由于属性列DE上第3、4、5行相同均为a4a5,所以将属性列C上的值均改为同一个符号a3。
-
根据CE→A,对上表进行处理,由于属性列CE上第3、4、5行相同均为a3a5,所以将属性列A上的值均改为同一个符号a1。
-
通过上述的修改,使第三行成为a1a2a3a4a5,则算法终止。且分解具有无损连接性。
∴综上:该分解具有无损连接性
分解的函数依赖保持性
设有关系模式R,F是R的函数依赖,Z是R的一个属性集合,则称Z所涉及到的F+中所有函数依赖为F在Z上的投影,记为:
∏ z(F)={x→y|x→y∈F+且xy⊆z}
意思就是对于R的属性依赖集F的闭包F+,R的一个属性集合Z涉及到在F+中的函数依赖叫做F在Z上的投影。对于每一个函数依赖所设计到的属性都应该在是Z中的属性。看这个数学表达式很好理解的。
设关系模式R的一个分解ρ={R1,R2,R3,…,RK},F是R的依赖集,如果F等价于∏R1(F) ∪ ∏R2(F) ∪… ∪ ∏RK(F) ,则称分解ρ具有函数依赖保持性。等价是什么意思?
例题:给定一个关系模式R(U,F),U={A,B,C,D},F={A → \rightarrow →B,B → \rightarrow →C,C → \rightarrow →D,D → \rightarrow →A},判断关系模式R的分解ρ={AB,BC,CD}是否具有依赖保持性。
∏AB(F)={A → \rightarrow →B,B → \rightarrow →A}
∏BC(F)={B → \rightarrow →C,C → \rightarrow →B}
∏CD(F)={C → \rightarrow →D,D → \rightarrow →C}
因为D+=ABCD,A∈D+,因此D → \rightarrow →A也得以保持,所以该分解具有依赖保持性。
一个无损连接分解不一定具有依赖保持性,反之,一个依赖保持性分解不一定具有无损连接性。
关系模式分解的主要类型
1、将关系模式分解为3NF,并保持函数依赖。
2、将关系模式分解为3NF,要求具有无损连接性并保持函数依赖
3、将关系模式分解成BCNF,使它具有无损连接性
对于第一种类型求解过程:
(1)先求Fmin
(2)查找有无不在F中出现的属性,如果有,就将它们构成一个关系模式,如果没有,则按左部相同的原则,对F进行分类
(3)将属于同一组的函数依赖的所有属性形成一个属性集U,并分别构成一个关系模式,则这种分解就保持函数依赖,并达到第3NF。
举例:
将关系模式R(C,T,H,I,S,G,K)转换为3NF,并保持函数依赖,其中F={CS→G,C→T,TH→I,HI→C,HS→I,HS → \rightarrow →C}
在本题中,F就是我们所需要求的Fmin,其中属性K不在F中,单独构成一个关系模式。左部相同的函数依赖是最后两个,则分成4种函数依赖:CS→G,C→T,TH→I,HI→C,(HS→I,HS → \rightarrow →C);因此模式分解为3NF的集合为ρ={R1(CSG),R2(CT),R3(THI),R4(HICS)}
对于第二种类型的求解过程:
(1)将关系模式转换成保持函数依赖的分解
(2)判断ρ是否具有无损连接性,若有则输出ρ
(3)否则,令ρ= ρ∪{X},其中X是R的候选关键字,即加上一个关系模式,属性都是候选关键字。
(4)输出ρ
举例:
将关系模式R(C,T,H,I,S,G)转换为3NF,并保持函数依赖和无损连接性,其中F={CS→G,C→T,TH→I,HI→C,HS→I}
解:先将R分解为保持函数依赖的分解:
ρ={R1(CSG),R2(CT),R3(THI),R4(HIC),R5(HSI)}经测试后发现具有无损连接性,所以ρ即所求解
对于第三种类型的求解过程:
(1)求出关系模式R的候选码
(2)判断R是否是BCNF,如果不是,则找出一个不符合BCNF的函数依赖,并将其进行分解。分解时,依据以下原则:设Ri中X→A不符合BCNF,则分解为Ri1(XA),Ri2(Ri-A),再判断Ri2(Ri-A)是否是BCNF,如果不是,再分解,直到每个函数依赖都满足BCNF为止。
举例:
将关系模式R(C,T,H,I,S,G)转换为BCNF,并使它具有无损连接性,F={CS→G,C→T,TH→I,HI→C,HS→I}
R的候选码是HS需要求解的,这一步省略写了,R不是BCNF,所以要进行分解。
(1)考虑CS→G不符合BCNF,将R分解成R1(CSG),将被确定的G去掉:R2(CTHIS),则F1={CS→G},
F2={C→T,TH→I,HI→C,HS→I},此时F2的候选码是HS
F2不符合BCNF,所以要对F2继续分解。
考虑F2中C→T不符合BCNF,所以分解为R21(CT),将被确定的T去掉,R22(CHIS)
F21={C→T }
F22={CH→I,HI→C,HS→I} ,此时F22的候选码是HS
F21已满足BCNF,F22不满足,因此对R22作进一步分解。
考虑CH→I与HI→C(这两个函数依赖含有的属性是一样的,归到同一个关系模式里面)不满足BCNF,因此将R22分解成
R221(CHI),R222(HIS),
F221={HI→C,CH→I},F221的候选码是HC、HI,符合BCNF
F222={HS→I},都满足BCNF
因此ρ={R1(CSG), R21(CT), R221(CHI),R222(HIS)}
参考文献
更多推荐
所有评论(0)