数据库规范化的产生主要是由模式设计(Schema Design)而推动的。模式设计的目标是为特定的数据库应用程序选择最合适的模式。模式的选择由用户提供和依赖项捕获的应用程序数据的语义信息指导。 常见的方法是从一个普遍的关系开始,并应用分解来创建满足某些形式的新关系,使用范式进行规范化就是其中之一。
根据约束强弱的差别,范式的种类从弱到强依次是:
(弱约束)1NF → 2NF → 3NF → BCNF → ... (强约束)
其中:
第一范式(1NF):不基于任何的约束,要求每个字段的值都是单一值,用于排除重复元组的出现。第二范式(2NF):满足第一范式,数据对表的主键与候选键有依赖关系。第三范式(3NF):满足第二范式,所有非主键属性都只和候选键有相关性,非主键属性之间独立无关。Boyce–Codd 范式(BCNF):满足第三范式,对于任意函数依赖 X → A,都满足 X 是 R 的一个超键。第四范式(4NF):每个非平凡的多值依赖都有一个超键。第五范式(5NF):候选键隐含了每个非平凡的连接依赖关系。第六范式(6NF):每个连接依赖都是平凡的。下面暂且详细介绍一下 BC 范式和第三范式。
一个数据库 R 满足,对于任意一个非平凡的函数依赖 X → A,X 都是一个超键(superkey)。
根据定义可知,当一个数据模式是 BCNF 时,基于函数依赖的所有数据冗余都会被清除。但是使用 BCNF 设计的数据模式不一定是一个好的设计。该范式的核心在于,不重复在数据库中描述同样的事实(值、函数依赖等)。
当我们对关系模式进行分解时,需要考虑以下两个特点:
无损耗连接(Lossless join):,将自然连接操作应用于分解后的关系时不允许生成假元组的可能性。依赖保留(Dependency preservation):确保每个功能依赖项都可以从分解后的功能依赖项中推断出来。根据上面的算法,最后得到的 S 中的每一个关系模式 R,都存在对应的函数依赖,且都满足 BC 范式。但最开始 ∑ 中的函数依赖并不一定会完全保留下来,有部分的函数依赖可能在分解过程中丢失了,但是这些依赖可以通过内连接不同的关系模式得到恢复。因此,BCNF 可以生成一个无损耗的分解,但不一定能生成一个既无损耗又能保留依赖的分解。
第三范式是一种比 BC 范式宽松一点的约束范式。与 BC 范式相比,第三范式总是可以保证无损耗连接和依赖保留,也就是说,满足第三范式的分解结果不会丢失原来的所有函数依赖。
一个数据库 R 满足,对于任意一个非平凡的函数依赖 X → A,X 都是一个超键(superkey)或者 A 是主要属性(prime attributes)。
由定义可知,满足第三范式的关系模式,可能会保留一些数据冗余,但排除了一些多余的函数依赖,比如:
部分函数依赖(Partial FD):X 是某个键的真子集,一个非主要属性 A 依赖于 X,则称 X → A 是部分函数依赖。传递函数依赖(Transitive FD):一个非主要属性 A 依赖于 X,但 X 不是任何键的真子集,则称 X → A 是传递函数依赖。例如,一个关系模式 R = { A,B,C,D},∑ = { A → B,B → C },其中它仅有一个键为 { A,D }。那么
A → B 是一个部分函数依赖(A 是键的真子集,B 不是主要属性)。B → C 是一个传递函数依赖(B 不是键的真子集,C 不是主要属性)。第三范式分解仅仅可以减少数据冗余,但不能完全消除,还是会存在一部分的冗余,因此满足 3NF 的数据模式仍然有可能会出现数据更新异常的现象。要想避免更新异常的情况,就要使用 BC 范式或者约束更强的范式来消除所有的冗余。
