接下来我们详细解释 BC 范式(Boyce-Codd范式,简称 BCNF),并通过具体例子说明其定义和应用。
一、BC范式的定义
BC范式(Boyce-Codd范式,BCNF)是数据库规范化理论中的一种范式,它比第三范式(3NF)更严格。其核心定义如下:
BCNF 定义:
在关系模式中,如果每个决定因素(即能够决定其他属性的属性或属性组)都包含候选键,则该关系模式满足 BCNF。换句话说,如果关系模式中不存在非平凡的函数依赖,使得决定因素不包含候选键,则该关系模式满足 BCNF。
关键点:
- 决定因素:一个属性或属性组,能够决定另一个属性或属性组。
- 候选键:能够唯一标识关系中每一行的属性或属性组。
- 非平凡函数依赖:指不是恒等式的函数依赖,例如 A → B,其中 A 和 B 是不同的属性。
BCNF 的目标是进一步消除冗余,确保数据的一致性,避免数据更新异常。
二、BC范式的例子
1. 初始表结构
假设我们有一个存储学生选课信息的表,但存在一些复杂的依赖关系:
表:StudentCourse
StudentID (学号) | CourseID (课程号) | Professor (教授) |
---|---|---|
1001 | CS101 | 李教授 |
1001 | CS201 | 王教授 |
1002 | EE101 | 赵教授 |
1003 | CS101 | 李教授 |
1003 | CS301 | 刘教授 |
在这个表中: |
- 候选键是 (StudentID, CourseID),因为它们共同唯一标识每一行。
- 存在函数依赖:CourseID → Professor(即课程号决定教授)。
2. 分析是否满足 BCNF
检查函数依赖 CourseID → Professor:
- 决定因素是 CourseID。
- CourseID 不是候选键(候选键是 (StudentID, CourseID))。
因此,这个关系模式不满足 BCNF,因为存在一个决定因素(CourseID)不包含候选键。
3. 分解以满足 BCNF
为了满足 BCNF,我们需要将表分解为两个关系模式,消除 CourseID → Professor 的依赖:
- 第一个关系模式:包含课程和教授的信息。
- 关系模式:Course (CourseID, Professor)
- 候选键:CourseID
- 函数依赖:CourseID → Professor
- 第二个关系模式:包含学生选课的信息。
- 关系模式:StudentCourse (StudentID, CourseID)
- 候选键:(StudentID, CourseID)
分解后的两个表:
Course 表:
CourseID (课程号) | Professor (教授) |
---|---|
CS101 | 李教授 |
CS201 | 王教授 |
EE101 | 赵教授 |
CS301 | 刘教授 |
StudentCourse 表:
StudentID (学号) | CourseID (课程号) |
---|---|
1001 | CS101 |
1001 | CS201 |
1002 | EE101 |
1003 | CS101 |
1003 | CS301 |
4. 验证 BCNF
- Course 表:
- 候选键:CourseID
- 所有函数依赖(如 CourseID → Professor)的决定因素都是候选键。
- 满足 BCNF。
- StudentCourse 表:
- 候选键:(StudentID, CourseID)
- 不存在其他函数依赖,只有候选键决定其他属性。
- 满足 BCNF。
三、总结
- BCNF 的核心要求:每个决定因素都必须是候选键,从而消除冗余和更新异常。
- 分解方法:通过将表分解为多个满足 BCNF 的子表,确保每个子表的函数依赖都满足 BCNF 的要求。
- 优点:进一步减少数据冗余,提高数据一致性和查询效率。
- 适用场景:适用于需要高数据一致性和低冗余的复杂关系模式。
接下来我们来详细解释第四范式(4NF)。
一、4NF的定义
第四范式(Fourth Normal Form, 4NF)是数据库规范化理论中的高级范式,它处理的是**多值依赖(Multivalued Dependency, MVD)**的问题。它建立在第三范式(3NF)或 Boyce-Codd 范式(BCNF)的基础之上。
4NF 的定义:
一个关系模式 R 属于第四范式(4NF),当且仅当,对于 R 中的每一个非平凡的多值依赖 X →→ Y(即 X 不能决定 R 的所有属性,Y 不是 R 的子集),X 都包含 R 的一个超键(Superkey)。
换句话说,在满足 4NF 的关系中,不允许存在非平凡的多值依赖,除非该依赖的决定因素(X)是一个超键。
关键概念:
- 多值依赖 (Multivalued Dependency, MVD):
- 与函数依赖(FD)不同,函数依赖是一个属性(或属性组)决定另一个属性的唯一值。而多值依赖是指一个属性(或属性组)可以对应另一个属性(或属性组)的多个独立的集合。
- 形式化表示:X →→ Y 意味着对于 X 的一个值,Y 可以有多个独立的值与之对应,并且这些 Y 的值与关系中的其他属性(Z)的值无关。
- 举例:如果
部门 →→ 部门经理
,那么一个部门可以有多个经理,这些经理的集合是独立的,与其他属性(如部门地点)无关。
- 非平凡多值依赖 (Non-Trivial MVD):
- 指的是
X →→ Y
,其中Y
不是R
的一个子集,并且X
不能决定R
的所有属性(即R - (X U Y)
不是空集)。
- 指的是
- 超键 (Superkey):
- 指关系模式中能够唯一标识元组的一个属性或属性组合,并且它可能包含多余属性(即它可能包含候选键之外的其他属性)。
为什么需要 4NF?
违反 4NF 的关系模式会导致数据冗余和插入、删除异常。当关系中存在非平凡的多值依赖且决定因素不是超键时,相关的多值属性集合必须作为一个整体出现或消失,这限制了数据的灵活性。
- 指关系模式中能够唯一标识元组的一个属性或属性组合,并且它可能包含多余属性(即它可能包含候选键之外的其他属性)。
二、4NF的例子
1. 初始表结构(违反 4NF)
假设我们有一个 Department
(部门)表,存储部门信息,包括部门名称、部门经理和部门地点。
表:Department
(DeptName, Manager, Location)
DeptName | Manager | Location |
---|---|---|
IT | Alice | Building A |
IT | Bob | Building A |
IT | Alice | Building B |
IT | Bob | Building B |
HR | Charlie | Building C |
HR | Charlie | Building D |
分析:
- 这个关系模式的关键属性可能是
(DeptName, Manager, Location)
的组合,但这显然不是好的键。 - 更合理的候选键可能是
(DeptName, Manager)
或(DeptName, Location)
,但这两个都不能唯一标识一个元组(例如,IT 部门有多个经理,有多个地点)。 - 实际上,
(DeptName)
可能是唯一能标识部门相关信息的属性。但是(DeptName)
并不能唯一标识表中的每一行。 - 这里存在两个独立的多值依赖:
DeptName →→ Manager
(一个部门有多个经理)DeptName →→ Location
(一个部门有多个地点)
- 这些多值依赖是非平凡的(
Manager
和Location
都不是DeptName
的子集,且R - (DeptName U Manager) = Location
和R - (DeptName U Location) = Manager
都不是空集)。 - 决定因素
DeptName
不是一个超键(因为它不能唯一标识表中的每一行)。 - 因此,这个
Department
表违反了 4NF。
问题: - 冗余: 每个经理-地点的组合都必须存在。例如,如果 IT 部门有 Alice 和 Bob 两个经理,在 Building A 和 Building B 两个地点,那么表里就必须有 4 行(Alice-A, Alice-B, Bob-A, Bob-B)。
- 插入异常: 如果想插入一个新的部门经理,但该部门尚未有地点信息,或者想插入一个新的部门地点,但该部门尚未有经理信息,都很难做到,因为
(DeptName, Manager, Location)
需要同时有值。 - 删除异常: 如果删除了 IT 部门在 Building A 的记录,可能会意外地删除了 Bob 是 IT 部门经理的信息(如果 Alice 只在 Building B)。反之亦然。
2. 分解为满足 4NF 的表
为了满足 4NF,我们需要将违反 4NF 的关系模式分解,使得每个新的关系模式中不再存在非平凡的多值依赖,或者这些依赖的决定因素是超键。
将 Department
表分解为三个表:
- 主表 (可选,用于存储部门基本信息,如果需要的话):
Departments
(DeptName) - DeptName 是主键。
- 分解多值依赖
DeptName →→ Manager
:DeptManagers
(DeptName, Manager)- 主键:
(DeptName, Manager)
(保证一个部门一个经理只出现一次) - 外键:
DeptName
引用Departments(DeptName)
- 分解多值依赖
DeptName →→ Location
:DeptLocations
(DeptName, Location)- 主键:
(DeptName, Location)
(保证一个部门一个地点只出现一次) - 外键:
DeptName
引用Departments(DeptName)
分解后的表:
表:Departments
(DeptName)
DeptName |
---|
IT |
HR |
表:DeptManagers
(DeptName, Manager)
DeptName | Manager |
---|---|
IT | Alice |
IT | Bob |
HR | Charlie |
表:DeptLocations
(DeptName, Location)
DeptName | Location |
---|---|
IT | Building A |
IT | Building B |
HR | Building C |
HR | Building D |
验证 4NF:
Departments
表:DeptName
是主键,也是唯一的超键。没有非平凡的多值依赖。满足 4NF。DeptManagers
表:- 候选键:
(DeptName, Manager)
,这也是唯一的超键。 - 检查多值依赖:是否存在
X →→ Y
?DeptName
可以决定Manager
,但这实际上是函数依赖DeptName → Manager
(在给定的元组范围内,一个 DeptName 对应一个唯一的 Manager 值,因为主键是(DeptName, Manager)
)。函数依赖是函数依赖的特殊情况,不违反 4NF。- 没有其他非平凡的多值依赖。
- 满足 4NF。
- 候选键:
DeptLocations
表:- 候选键:
(DeptName, Location)
,这也是唯一的超键。 - 检查多值依赖:类似
DeptManagers
表,DeptName → Location
是函数依赖。 - 没有其他非平凡的多值依赖。
- 满足 4NF。
优点:
- 候选键:
- 消除冗余: 现在,IT 部门的经理和地点信息存储在单独的表中,不再需要重复组合。
- 避免异常: 可以独立地插入、删除或更新经理信息或地点信息,而不会影响其他信息。例如,可以轻松添加一个新的 IT 部门经理,即使还没有指定地点;可以删除 IT 部门在 Building A 的信息,而不会删除 Bob 作为 IT 部门经理的信息。
三、总结
- 4NF 目标: 消除由非平凡多值依赖引起的冗余和更新异常。
- 核心要求: 关系模式中所有非平凡的多值依赖的决定因素都必须是超键。
- 分解方法: 将具有非平凡多值依赖且决定因素不是超键的关系模式,分解为多个关系模式,每个模式只包含一个独立的多值依赖。
- 适用场景: 当关系模式中存在多个独立的多值属性集合时,应考虑应用 4NF。
- 关系: 4NF 是比 BCNF 更强的规范化形式。如果关系满足 4NF,则它一定也满足 BCNF。