关系模式的第三范式(3NF)
若一个关系模式满足第二范式,并且每一个非键属性都不传递函数依赖于任何一个候选键,那么就称该关系模式是满足第三范式(third normal form,3NF)的。比如下图左侧的关系模式便不满足第三范式:
与第二范式类似,不满足第三范式的关系模式可能存在以下几个问题(以图中左侧关系模式为例,其中
{StudentId}
是一个候选键同时也是主键):
- 插入异常。若要向表中添加一个新部门的信息,但还未招收学生,那么会导致
StudentId
等字段的值为空,这是不被允许的;- 修改复杂。若某部门(比如
CS
)的信息需要更新,这需要同时修改Department Location
字段的第 1、2 行处的值;
而将其规范化为满足第三范式的右侧几个关系模式后,将不再存在上述问题,并且数据冗余减少、占用的存储空间也会下降
关系模式的 3NF 规范化(合成法)
给定一个关系模式 R ( U , F ) R(U,F) R(U,F),按照下面的算法可以得到一个对该模式的保持函数依赖的分解 ρ \rho ρ,使其规范化为满足 3NF 的一组子关系模式:
- 对 R ( U , F ) R(U,F) R(U,F) 中的函数依赖集 F F F 进行极小化处理,处理后的依赖集记为 F ′ F' F′;
- 找出所有不在 F ′ F' F′ 中出现的属性(记为 U 0 U_0 U0),构成一个关系模式 R 0 ( U 0 , F 0 ) R_0(U_0,F_0) R0(U0,F0),记 U ′ = U − U 0 U'=U-U_0 U′=U−U0;
- 若有 X → A ∈ F ′ X\to A\in F' X→A∈F′ 且 X ∪ A = U ′ X\cup A=U' X∪A=U′,那么 ρ = { R ( U , F ) } \rho=\{R(U,F)\} ρ={R(U,F)},算法终止;
- 否则,对 F ′ F' F′ 中的全部函数依赖按具有相同左部的原则分组,假定分得 k k k 组,每一组函数依赖所涉及的全部属性形成一个属性集 U i U_i Ui(若有 U i ⊆ U j ( i ≠ j ) U_i\sube U_j(i\neq j) Ui⊆Uj(i=j) 就去掉 U i U_i Ui);
- 于时最终 ρ = { R 1 ( U 1 , F 1 ) , ⋯ , R k ( U k , F k ) } ⋃ R 0 ( U 0 , F 0 ) \rho=\{R_1(U_1,F_1),\cdots,R_k(U_k,F_k)\}\bigcup R_0(U_0,F_0) ρ={R1(U1,F1),⋯,Rk(Uk,Fk)}⋃R0(U0,F0),算法终止.
首先知道,按上面过程得到的分解是保持函数依赖的,其次可以证明得到的 k k k 个( R 0 R_0 R0 可以并入其中的一个)子关系模式都是满足 3NF 的。
当然,按该合成法得到的分解的一组子关系模式有可能还满足 BCNF(不妨以〖Boyce-Codd 范式(BCNF)〗中的例子进行测试),但普适性未加保证,需要的话可改用〖关系模式的 BCNF 规范化(分解法)〗。
以前面的示例R(StudentId, StudentName, Department, DepartmentLocation)
来进行演示:
- 分析该模式中所有的函数依赖,得到 F ′ = { S t u d e n t I d → S t u d e n t N a m e , S t u d e n t I d → D e p a r t m e n t , D e p a r t m e n t → D e p a r t m e n t L o c a t i o n } F'=\{StudentId\to StudentName,\,StudentId\to Department,\,Department\to DepartmentLocation\} F′={StudentId→StudentName,StudentId→Department,Department→DepartmentLocation};
- 所有属性都已在 F ′ F' F′ 出现,因而 U 0 = ∅ U_0=\varnothing U0=∅,继续;
- 不存在该种情况,继续;
- 按相同左部原则分组,得到 F 1 = { S t u d e n t I d → S t u d e n t N a m e , S t u d e n t I d → D e p a r t m e n t } F_1=\{StudentId\to StudentName,\,StudentId\to Department\} F1={StudentId→StudentName,StudentId→Department} 和 F 2 = { D e p a r t m e n t → D e p a r t m e n t L o c a t i o n } F_2=\{Department\to DepartmentLocation\} F2={Department→DepartmentLocation},以及 U 1 = { S t u d e n t I d , S t u d e n t N a m e , D e p a r t m e n t } U_1=\{StudentId,StudentName,Department\} U1={StudentId,StudentName,Department} 和 U 2 = { D e p a r t m e n t , D e p a r t m e n t L o c a t i o n } U_2=\{Department,DepartmentLocation\} U2={Department,DepartmentLocation};
- 于是最终 ρ = { R 1 ( U 1 , F 1 ) , R 2 ( U 2 , F 2 ) } \rho=\{R_1(U_1,F_1),R_2(U_2,F_2)\} ρ={R1(U1,F1),R2(U2,F2)},这正与前面图中右侧的模式组一致。
确保具有无损连接性
经过上面的算法得到保持函数依赖的分解 ρ = { R 1 ( U 1 , F 1 ) , ⋯ , R k ( U k , F k ) } ⋃ R 0 ( U 0 , F 0 ) \rho=\{R_1(U_1,F_1),\cdots,R_k(U_k,F_k)\}\bigcup R_0(U_0,F_0) ρ={R1(U1,F1),⋯,Rk(Uk,Fk)}⋃R0(U0,F0) 后,可以再执行下述步骤进一步使其具有无损连接性:
- 假设 X X X 是 R ( U , F ) R(U,F) R(U,F) 的一个候选键,令 τ = ρ ∪ R ∗ ( X , F x ) \tau = \rho\cup R^*(X,F_x) τ=ρ∪R∗(X,Fx),其中 R ∗ ( X , F x ) R^*(X,F_x) R∗(X,Fx) 表示仅由 X X X 构成的关系模式;
- 若存在某 U i U_i Ui,使得 X ⊆ U i X\sube U_i X⊆Ui,则将 R ∗ ( X , F x ) R^*(X,F_x) R∗(X,Fx) 从 τ \tau τ 中去除;使得 X ⊇ U i X\supe U_i X⊇Ui,则将 R i ( U i , F i ) ) R_i(U_i,F_i)) Ri(Ui,Fi)) 从 τ \tau τ 中去除;
- τ \tau τ 即是所求的分解。
这样最终得到的
τ
\tau
τ 就是具有无损连接性的分解(可以证明),并且保持了函数依赖,同时还满足 3NF。以下面的R(StudID, CourseID, StudName, CourseName)
(数据依赖有StudID
→
\to
→StudName
和CourseID
→
\to
→CourseName
)例子演示了该额外步骤的必要性:
关系模式的 Boyce-Codd 范式(BCNF)
假设关系模式 R ( U ) R(U) R(U) 满足第一范式,对于 U U U 的任意两个属性子集 X , Y ( X ⊉ Y ) X,Y\,(X\not\supe Y) X,Y(X⊇Y),若 X → Y X\to Y X→Y 时必有 X X X 包含某候选键,那么就称该关系模式是满足 Boyce-Codd 范式(Boyce-Codd normal form,BCNF)的。比如下图左侧的关系模式虽然满足第三范式,但不满足 BCNF(该场景语义下规定一个教师只教一个项目):
可以证明,满足 BCNF 的关系模式一定满足第三范式(反之不然),因此通常也认为 BCNF 是扩充的(或修正的)第三范式。下图左侧的关系模式中,由于
{StudentId, ProjectId}
和{StudentId, TeacherId}
都是候选键,因而不存在非键属性,进而该模式满足 3NF;但由于{ProjectId}
→ \to →{TeacherId}
,而{ProjectId}
不包含候选键,于是不满足 BCNF。满足 3NF 但不满足 BCNF 的关系模式,同样可能会存在插入异常和修改复杂的问题,比如图中左侧表要添加新项目必须同时添加学生、要修改某项目信息得同时修改多处
通俗来讲就是,BCNF 要求关系模式中的决定因素(determinant)必须包含候选键,由此可以得到关于 BCNF 的等价定义:若一个关系模式的非主键属性都是完全函数依赖于主键的,那么就称该关系模式是满足 Boyce-Codd 范式的。
任何一个关系模式都可以按照合成分解法分解成满足 BCNF 的一组子关系模式
另外值得一提的是(纠正文章 Normalization in SQL (1NF - 5NF): A Beginner’s Guide 中的错误判断),下图右左两侧的两个关系模式都是满足 BCNF 的(不管场景是否规定一本书只能被一个人借一次):
关系模式的 BCNF 规范化(分解法)
给定一个关系模式 R ( U , F ) R(U,F) R(U,F),按照下面的算法可以得到一个关于该模式的无损连接分解(但不保证是保持函数依赖的) ρ \rho ρ,使其规范化为满足 BCNF 的一组子关系模式:
- 令 ρ = R ( U , F ) \rho=R(U,F) ρ=R(U,F);
- 检查 ρ \rho ρ 中各关系模式是否均属于 BCNF,若是,则算法终止;
- 设 ρ \rho ρ 中存在 R i ( U i , F i ) R_i(U_i,F_i) Ri(Ui,Fi) 不属于 BCNF,那么必有 X → A ∈ F i + ( A ∉ X ) X\to A\in F_i^+\,(A\notin X) X→A∈Fi+(A∈/X) 且 X X X 不包含 R i R_i Ri 的候选键。因此 X ∪ A X\cup A X∪A 是 U i U_i Ui 的真子集,于是对 R i R_i Ri 进行分解: σ = { S 1 ( X ∪ { A } , F S 1 ) , S 2 ( U i − { A } , F S 2 ) } \sigma=\{S_1(X\cup\{A\},F_{S_1}),\enspace S_2(U_i-\{A\},F_{S_2})\} σ={S1(X∪{A},FS1),S2(Ui−{A},FS2)},以 σ \sigma σ 代替 R i ( U i , F i ) R_i(U_i,F_i) Ri(Ui,Fi),返回第 2 步;
由于 U U U 中属性有限,因而有限次循环后算法一定会终止。这是一个自顶向下的算法,它自然地形成一个对 R ( U , F ) R(U,F) R(U,F) 的二叉分解树(不一定唯一,与选定的“ X → A X\to A X→A”有关)。
该算法经过严格证明的有效的,可以上面的
R(StudentId, ProjectId, TeacherId)
模式为例进行测试。由于不保证得到的分解是保持函数依赖的,因此需要的话可考虑改用〖关系模式的 3NF 规范化(合成法)〗。