一、第一范式(First Normal Form)
关系模型的属性值域有原子性(atomic)和非原子性之分,以下三者为非原子性的值域
- 复合属性
- 多值属性
- 复杂数据类型
关系模式R满足第一范式,当且仅当其所有属性均满足原子性。
对于关系数据库,所有数据库中的关系模型都应当满足第一范式。
第一范式下关系数据库的缺陷
- 可能存在冗余,包括存储与查询方面
- 更新时可能产生异常(表的级联)
- 插入删除时可能产生异常
二、关系的分解(Decomposition)标准
例子:含有(ABCD)属性的关系可以分解为(AB)和(BCD),(ACD)和(ABD)等多种样式。
分解有以下规则和要求(其中,第1,2条是硬性要求):
- 分解后的所有子关系的集合的并必须等于原关系: R = ∪ i = 1 n R i R= \cup_{i=1}^nR_i R=∪i=1nRi
- 应满足无损连接分解(lossless-join decomposition)条件
解释:对被分成R1和R2的关系r,应有:
r = ∏ R 1 ( r ) ⋈ ∏ R 2 ( r ) r=\prod_{R_1}(r)\bowtie\prod_{R_2}(r) r=∏R1(r)⋈∏R2(r)
三、函数依赖(Funtional Dependencies,FD)
定义:令R为目标关系模式,
α
\alpha
α和
β
\beta
β为其中的属性,则:
函数依赖
α
→
β
\alpha\rightarrow\beta
α→β在R上成立当且仅当对任意的合理关系r( R ),其中任意两个元组
t
1
,
t
2
的
α
t_1,t_2的\alpha
t1,t2的α属性相同时,
β
\beta
β属性下的值也必定相同,也即
t
1
[
α
]
=
t
2
[
α
]
⇒
t
1
[
β
]
=
t
2
[
β
]
t_1[\alpha]=t_2[\alpha]\Rightarrow t_1[\beta]=t_2[\beta]
t1[α]=t2[α]⇒t1[β]=t2[β]
此时,称β函数依赖于α,α函数决定β。
验证:对于给定的关系实例,只要B属性确定时,A属性也唯一确定,则B
→
\rightarrow
→A就有可能成立,而在关系实例上就可以认为已经成立
1. 函数依赖与“键(key)”的关系
函数依赖事实上是键概念的扩展,它们之间有以下关联:
- K是关系模式R的超键(super key)当且仅当 K → R K\rightarrow R K→R
- K是R的候选键(candidate key)当且仅当
- K → R K\rightarrow R K→R,并且
- 不存在K的真子集α,满足 α → R \alpha\rightarrow R α→R
FD的性质也对应了“键”的性质。
2. 函数依赖的平凡/非平凡性
如果一个函数依赖在所有关系上都能被满足,那么它是平凡的(trivial)
例子: A → A , A B → A A\rightarrow A,AB\rightarrow A A→A,AB→A
总体上, 当 β ⊆ α 时 , α → β 当\ \beta\subseteq\alpha时,\alpha\rightarrow\beta 当 β⊆α时,α→β为平凡函数依赖,否则就是非平凡函数依赖。
3. 函数依赖集的闭包(closure)
定义:给定函数依赖集合F,所有能被F逻辑推理出来的函数依赖(当然包括其本身)被称为其闭包(closure),记为
F
+
F^+
F+。
例子:
A
→
B
,
B
→
C
,
t
h
e
n
A
→
C
A\rightarrow B,B\rightarrow C,then\ A\rightarrow C
A→B,B→C,then A→C
3.1 闭包计算:阿姆斯特朗公理(Armstrong`s Axioms)
- (reflexivity,自反律):if β⊆α, then α→β --平凡FD情况
- (augmentation,增补律):if α→β, then γα→γβ
- (transitivity,传递律):if α→β, and β→γ, then α→γ
补充定理:
- (union,合并律):If α→β and α→γ, then α→βγ
- (decomposition,分解律):If α→βγ, then α→β and α→γ
- (pseudotransitivity,伪传递律):If α→β and γβ→δ, then αγ→δ
通过以上若干公理、定理的反复使用,可以从函数依赖集中计算其闭包
3.2 计算闭包的一般过程
伪代码如下:
Fp = F
repeat
for each FD f in Fp
对f使用自反律和增补律
将产生的新FD添加入Fp中
for each pair of FD f1 and f2 in Fp
如果f1和f2符合传递律的条件
将传递律的结果添加到Fp
until Fp不再改变
3.3 属性集的闭包
定义:对于指定的属性集 α \alpha α,将在F下由它所直接和间接函数决定的属性的集合称为其在F下的闭包(记作 α + \alpha^+ α+),注意属性集的闭包仍是属性集,而不是属性集上的函数依赖
- 属性集的闭包的定义可以用于检验属性集是否是超键(super key):
α 是 s u p e r k e y ↔ α → R i s i n α + \alpha是super\ key\leftrightarrow\alpha\rightarrow R\ is\ in\ \alpha^+ α是super key↔α→R is in α+
事实上,属性集闭包就是从 F + F^+ F+中取出条件为 α \alpha α的函数依赖集合,但有更高效的属性集闭包的求法:
result = α
while(result相较之前改变){
for each α→β in F{// β可能是复合的
if (β属于result)
result = result∪γ
}
α+ = result
}
这避免了对 F + F^+ F+的计算。
一些例子:
从这一例子可以看出,候选码(candidate key)并不是唯一的,计算时应当考虑所有可能
3.4 属性闭包的应用
- 用于确定某个属性集是否为超键
- 用于确定函数依赖是否成立:如果 β \beta β在 α + \alpha^+ α+中,那么 α → β \alpha\rightarrow\beta α→β成立,反之则不成立。
- 计算整个函数依赖的闭包 F + F^+ F+,过程如下:
F+ = {}
for each γ⊆R{
find γ+
for each S⊆γ+{
put γ→S into F+
}
}
F+ is the result
3.5 正则覆盖(Canonical Cover)
简而言之,正则覆盖(记作
F
c
F_c
Fc)是对函数依赖集F的简化,它保有了F的所有含义,但去除了冗余的内容。
正则覆盖的计算思路就是去除无关属性(extraneous attribute),它存在于F中时,有三种可能:
- F中,有些FD可以从其他FD推出
- 一些FD的左侧属性可能是冗余的(redundant)
例子:
对应的判断方法: 对 于 F D : α → β , 左 侧 属 性 A 在 α 中 无 用 ( e x t r a n e o u s ) ⟷ F 能 够 逻 辑 推 出 F ’ = ( F – { α → β } ) ∪ ( ( α – A ) → β ) 对于FD:α→β,左侧属性A在α中无用(extraneous)\longleftrightarrow\\F能够逻辑推出 F’=(F–\{α→β\}) ∪((α–A) →β) 对于FD:α→β,左侧属性A在α中无用(extraneous)⟷F能够逻辑推出F’=(F–{α→β})∪((α–A)→β)
例子:
事实上实际计算时,只需要计算(
α
−
A
)
+
\alpha-A)^+
α−A)+是否蕴含
β
\beta
β,是则冗余,否则不冗余
3. 一些FD的右侧属性可能是冗余的(redundant)
例子:
类似的判断方法: 对 于 F D : α → β , 右 侧 属 性 A 在 β 中 无 用 ( e x t r a n e o u s ) ⟷ F ’ = ( F – { α → β } ) ∪ ( α → ( β – A ) ) 能 够 逻 辑 推 出 F 对于FD:α→β,右侧属性A在β中无用(extraneous)\longleftrightarrow F’= (F–\{α→β\}) ∪(α→(β–A))能够逻辑推出F 对于FD:α→β,右侧属性A在β中无用(extraneous)⟷F’=(F–{α→β})∪(α→(β–A))能够逻辑推出F。
对应的例子:
正则覆盖的计算方法:
Fc = F
do{
利用结合律将Fc中α1→β1和α1→β2转化为α1→β1β2
找出有左侧冗余或右侧冗余的FD,并删除无用属性
}until(Fc不再变动)
例子:
四、规范化的关系分解
将关系分解后的若干关系子集应当维持良好结果(good form),除了(二)中提到的硬性要求:分解完整性和无损连接性,还有一个重要的性质:依赖保持性(dependency preservation)。
顾名思义,依赖保持的含义就是原关系模式中存在的FD,分解后的子关系集合应当尽量保持。另外,分解也应当做到尽量减少冗余。
- 无损连接分解的判断条件:
{ R 1 ∩ R 2 } → R 1 o r { R 1 ∩ R 2 } → R 2 \{R_1\cap R_2\}\rightarrow R_1\ or\ \{R_1\cap R_2\}\rightarrow R_2 {R1∩R2}→R1 or {R1∩R2}→R2 - 依赖保持性的分解条件: ∪ i = 1 n F i + = F + \cup_{i=1}^nF_i^+=F^+ ∪i=1nFi+=F+
- 无冗余性条件:分解后的子关系集应当满足BC范式(BCNF)和第三范式(3NF)的其中之一。
例子:
依赖保持性的简化检查
以上是对FD:
α
→
β
\alpha\rightarrow\beta
α→β是否在分解的结果中仍然存在的的验证;当且仅当
β
⊆
r
e
s
u
l
t
\beta\subseteq result
β⊆result时,这一条函数依赖被保持
BC范式(Boyce-Codd Normal Form)
定义:如果具有函数依赖F的关系R符合BC范式,则对于 F + F^+ F+中的任意一个函数依赖 α → β \alpha\rightarrow\beta α→β,以下两条中至少一条将成立:
- α → β \alpha\rightarrow\beta α→β是平凡的
- α \alpha α是R的超键
例子:
BC范式的测试
简化后的测试:
BC范式的分解
分解算法如下:
思想:对不满足BC范式的关系R,找到一个非平凡的,导致BC范式不满足的函数依赖
α
→
β
\alpha\rightarrow\beta
α→β,将R分解为
(
α
,
β
)
和
(
R
−
β
)
(\alpha,\beta)和(R-\beta)
(α,β)和(R−β)。
例子:
BC范式与依赖保持
事实上BC范式并不总能做到依赖保持(dependency preserving)
因此,需要一个稍弱于BC范式从而达成依赖保持,但仍然能够减少冗余的分解方法,这一方法就是第三范式(Third Normal Form,3NF)。
第三范式
定义:关系模式R在满足以下条件时,满足第三范式(3NF):
对于
F
+
F^+
F+中的任一函数依赖
α
→
β
\alpha\rightarrow\beta
α→β,以下约束至少有一条成立:
- α → β \alpha\rightarrow\beta α→β是平凡的
- α \alpha α是R上的超键
- 所有 β − α \beta-\alpha β−α内的属性都被包括在R的一个候选键(candidate key)中(注意到这里的减号表示集合的差)
可以看出,第三范式定义中的第三条就是对BC范式的妥协(compromise),并且显然满足BC范式的分解必然满足第三范式。
例子:
对3NF的测试
对于单个关系R,仍然只用检验F而非 F + F^+ F+中的FD。另外,正则覆盖和属性的闭包概念也在第三范式的判定算法中有体现,算法描述如下:
let Fc be the canonical cover for F
i = 0
for each FD α→β in Fc{
if(不存在R[j],其中1 ≤j ≤i,包含α和β){
i = i + 1
R[i] = (α,β)// 将Fc中的每个FD分解为子模式(α,β),进而保证dependency-preserving
}
if(不存在R[j],其中1 ≤j ≤i,含有关系R的一个候选码){
i = i + 1
R[i] = R的任意一个候选码// 保证至少在一个R[i]中存在R的候选码,从而保证lossless-join
}
}
(R[1],...,R[i])即为第三范式分解的结果
例子:
例子2:
例子3:
例子4:
多值依赖(Multivalued Dependencies)
多值属性是BC范式/第三范式不能充分覆盖的部分。