数据库模式分解
部分函数依赖
函数依赖的确定
- 1对1的关系时,有两个函数依赖
- 1对多时,有一个函数依赖
- 多对多时,没有函数依赖
函数依赖类型
右
边
不
为
左
边
的
子
集
{
非
平
凡
函
数
依
赖
(
A
−
>
B
)
,
y
e
s
平
凡
函
数
依
赖
(
A
B
−
>
B
)
,
n
o
左
边
有
子
集
能
决
定
右
边
{
部
分
函
数
依
赖
,
y
e
s
完
全
函
数
依
赖
,
n
o
右边不为左边的子集 \begin{cases} 非平凡函数依赖(A->B),yes \\ 平凡函数依赖(AB->B),no \end{cases}\\ 左边有子集能决定右边 \begin{cases} 部分函数依赖,yes\\ 完全函数依赖,no \end{cases}
右边不为左边的子集{非平凡函数依赖(A−>B),yes平凡函数依赖(AB−>B),no左边有子集能决定右边{部分函数依赖,yes完全函数依赖,no
传递函数依赖A->B,B->C,此时A—>C就是传递函数依赖
码和主属性
候选码:能够唯一决定一个元组的属性集叫做码
主属性:码里的属性就叫主属性
非主属性:不在码里的属性
超键:码或子集是码的属性集合
候选码求取理论
根据函数依赖,把属性分成四类
L:只在函数依赖左侧
R:只在函数依赖右侧
LR:函数依赖两侧
N:没有出现过的
L、N属性是候选码的子集,若L、N属性的闭包能涵盖全部的元素,则其是唯一候选码
若不能,则从LR元素中于L、N元素进行组合,组合后的元素集的闭包能够涵盖全部元素,即为候选码。
1NF
能写出来的二维表都叫第一范式
2NF
不存在非主属性对码的部分函数依赖(传递函数依赖)
3NF
对每个非平凡依赖,或左边为超键,或右边全部由主属性构成
推论:每一个非主属性,既不部分依赖于码,也不传递依赖于码
分解算法
对所有函数依赖,先将函数依赖集化成最小函数依赖集,只要左边相同,就把他们合并起来,形成的集合作为符合3NF的一个属性集。
例子:
A->B,AB->C,D->AC,D->E
最小函数依赖集:
第一步:先把右边有多个的拆成右边只有一个的
A->B,AB->C,D->A,D->C,D->E
第二步:去除左边的冗余项
因为A->B,AB->C冗余了,所以有B->C
结果为:A->B,B->C,D->A,D->C,D->E
第三步:去除传递函数依赖
D->A->B->C,去除D->C
最终结果为:
A->B,B->C,D->A,D->E
开始3NF的分解
第一步:
找候选码
L:D R:C,E
N: LR:A,B
对D求闭包,最终能够包含全部元素集合,因此D是该元素集合的唯一候选码
第二步:于是遵循左部相同合并原则,对其进行合并,形成属性集
R1={A,B}
R2={D,A,E}
R2={B,C}
第三步:查看上述集合有没有包含关系,如果有就吸收合并
显然上面没有
第四步:看分的属性组中有没有包含码,如果有就是无损且保持函数依赖的3NF,没有包含就不是无损且保持函数依赖的3NF,就添加一个属性组,把原来关系的码加进去
最终得到结果为:
R1={A,B}
R2={D,A,E}
R2={B,C}
这三个关系集上的函数依赖均满足3NF的要求
投影算法
假设有关系R(A,B,C,D,E)和FD集{AB->DE,C->E,D->C,E->A},假设要把这些FD投影到S(A,B,C),求出在S上成立的FD集合
第一步:将原来的FD转换成右边只有一个的情况
AB->D,AB->E,C->E,D->C,E->A
第二步:通过直接观察,或传递依赖,找到S(A,B,C)上的函数依赖
AB->D->C 即AB->C
C->E->A 即C->A
所以在S上成立的FD集合为{AB->C,C->A}
BCNF
对于任意一个函数i依赖,左边全为超键,即左边永远能退出整个属性集合。
例子,沿用上一题化最小函数依赖集的结果
A->B,A->C,D->A,D->E
A->B不符合BC范式的要求
对A进行闭包,形成属性集R1 =(A)+={A,B,C}
属性集R2为:U-R1+{A} = {A,D,E}
在R1中的最小函数依赖集为:A->B,A->C ,此时A为这个属性集R1{A,B,C}的码,并且满足BCNF的要求,分解停止
在R2中的最小函数依赖集为:D->A,D->E,此时D为这个属性集R2{A,D,E}的码,并且满足BCNF的要求,停止分解
最终分解成两个属性集:
R1{A,B,C}
R2{A,D,E}
这两个关系集上的函数依赖均满足BCNF的要求,同时也满足3NF的要求。
无损连接的chase检查法
直接上例子
用上面的:
R(A,B,C,D,E)
A->B,A->C,D->A,D->E
R1(A,B,C)
R2(A,D,E)
这个直接列表,每个属性集一行,每行|R|个属性
属性集 | A | B | C | D | E |
---|---|---|---|---|---|
{A,B,C} | a | b | c | d1 | e1 |
{A,D,E} | a | b2 | c2 | d | e |
在属性集中的元素,就可以直接用小写字母表示,否则则用,小写字母+下标行号表示
根据函数依赖,如果左边的值在表中对应列的值是一致的,右边也应该一致,如果不一致,就向行号小的同步。
如A->B,A列一致,则需要使得B也一致
属性集 | A | B | C | D | E |
---|---|---|---|---|---|
{A,B,C} | a | b | c | d1 | e1 |
{A,D,E} | a | b | c | d | e |
A->C,A列一致,则C列也应该一致
此时第而行中的数据全为小写字母,这时候就能说明,这种分解方式是无损的。
某个函数依赖的闭包是否属于函数依赖集的闭包
设有关系R(A,B,C,D,E),对应的函数依赖集F={AB->D, AC->E, BC->D, D->A, E->B},
判定
1.函数依赖AE->CD 是否属于F+?▁▁▁(填是或否)
2.函数依赖CD->BE 是否属于F+?▁▁▁(填是或否)
对左边,根据F的函数依赖求闭包,如果左边的闭包 包含{左边+右边}则,说明该函数依赖属于F+
第一题:
(AE)+ = {AEBD} 不包含 {AECD},所以AE->CDu不属于F+
第二题:
(CD)+ = {CDAEB} 包含{CDBE},所以CD->BE属于F+