回到首页 / 上级目录

规范化

关系数据库中,关系模式的设计需要满足一定要求,称这些要求为范式。

范式的层次由低到高分为六种:1NF、2NF、3NF、BCNF、4NF、5NF。

范式的层次越高,要求越严格。

数据依赖

介绍范式之前,得先了解数据依赖。

数据依赖分为两种:函数依赖和多值依赖。

1. 函数依赖

以关系模式 R(A, B, C, D, E) 为例:

属性间的关系如下:

(A, B) -> E
A -> C
C -> D

其中 X -> Y 表示 X 的取值 x 唯一标识 Y 的取值 y。

主键为 (A, B),主键里的属性称为主属性,其他属性称非主属性。

E 由所有主属性共同决定,称 E 完全依赖于主键,是多对一的关系。

C 仅由主键中的属性 A 决定,称 C 部分依赖于主键,是一对一的关系。

D 通过 C 由属性 A 决定,称 D 传递依赖于 A。

2. 多值依赖

以关系模式 R(X, Y, Z) 为例:

其中 (X, Y) ->-> Z 表示 (X, Y) 的取值 (x, y) 对应 Z 的多个值 {z1, z2, …}。

若 Z 的取值仅和 X 有关,则称 (X, Y) ->-> Z多值依赖

若 Y 为空集,则称 X ->-> Z 为平凡的多值依赖,是多对多的关系。

若 Y 不为空集,则称 (X, Y) ->-> Z 为非平凡的多值依赖,是一对多的关系。

1NF

1NF 要求属性不能再继续分解,且重复元组。

有时因为业务需求和优化查询效率,可以不遵循 1NF。

2NF

在 1NF 基础上,2NF 要求非主属性完全函数依赖于主键。

以 R(学生 ID, 课程 ID, 成绩, 系名) 为例:

在关系模式 R 中,(学生 ID, 课程 ID) 是主键。

系名仅由学生 ID 决定,即系名部分函数依赖于主键。

关系模式 R 会产生以下几个问题:

(1)插入异常:插入 (学生 ID, 系名) 时,由于主键不全,导致插入失败。

(2)删除异常:若学生只选了一门课,删除该课程会导致信息丢失(系名和学生 ID)。

(3)数据冗余:如果学生转系,需要修改多个元组。

解决方法是将 R 分解成 S(学生 ID, 系名) 和 C(学生 ID, 课程 ID, 成绩)。

可通过自然连接合并 S 和 C 获得 R。

3NF

在 2NF 基础上,非主属性不函数依赖于其他非主属性。

举一个不满足 3NF 的例子:R(学生 ID, 系名, 学生住处)。

在 R 中,学生 ID 是主键。

学生住处函数依赖于非主属性系名,因此关系模式 R 不满足 3NF。

若一个关系不满足 3NF,就会产生 2NF 相类似的问题。

解决方法是将 R 分解为 S(学生 ID,系名) 和 D(系名,学生住处)。

BCNF

BCNF 也称为扩充的 3NF。

在 3NF 基础上,BCNF 消除了主属性对其他属性的依赖。

举一个不满足 BCNF 的例子:R(学生 ID,教师 ID,课程 ID)。

在 R 中,每个教师只教一门课,每门课有若干教师,某一学生选定某门课,就对应一个固定的教师。

由语义可得如下的函数依赖项:

(学生 ID, 课程 ID) --> 教师 ID
(学生 ID, 教师 ID) --> 课程 ID
教师 ID --> 课程 ID

其中 (学生 ID, 课程 ID) 和 (学生 ID, 教师 ID) 均可作为主键。

若以 (学生 ID, 课程 ID) 作为主键,则主属性课程 ID 依赖于非主属性教师 ID,不满足 BCNF。

若以 (学生 ID, 教师 ID) 作为主键,则非主属性课程 ID 部分依赖于主键,不满足 2NF,也就不满足 BCNF。

解决方法是将 R 分解为 S(学生 ID, 教师 ID) 和 T(教师 ID,课程 ID)。

BCNF 在函数依赖范畴内实现了彻底的分离,已消除了插入和删除的异常。

4NF

在 BCNF 基础上,消除非平凡多值依赖。

以存在非平凡多值依赖的关系模式 R(X, Y, Z) 为例,其非平凡多值依赖为 (X, Y) ->-> Z

R 的操作会有如下问题:

(1)插入繁琐:若要增加 Y 的值 y1,需插入多个元组。

(2)删除繁琐:若要删除 Y 的值 y1,需删除多个元组。

(3)更新繁琐:若要更新 Y 的值 y1,需更新多个元组。

(4)数据冗余:对于 Z 不同的取值,(X,Y) 要存储多个元组。

解决方法是将 R 拆解为 S(X, Y) 和 T(X, Z)。

本质是将多对多的关系转化为一对多的关系。

规划化

规范化(normalization)是一个过程,逐步消除数据依赖中不合适的部分。

规范化是通过对关系模式的分解来实现的,即把低一级的关系模式分解为若干个高一级的关系模式。

4NF 已经解决函数依赖和多值依赖的问题,5NF 处理连接依赖,这里不再讨论。

需要注意的是,过度规范化的设计可能会导致查询的复杂性增加,从而影响查询性能。

有时候为了业务需求和优化查询效率,关系模式甚至不符合 1NF。