1. 什么是第三范式?
第三范式的核心目标是:消除数据冗余和避免更新异常。
它的定义基于第二范式,并增加了一个更严格的要求:
一个关系(表)必须首先满足第二范式(2NF),并且表中的所有非主属性都必须直接依赖于主键,而不能存在传递依赖。
理解这个定义的关键在于两个概念:非主属性 和 传递依赖。
2. 核心概念解析
非主属性
-
主属性:属于任何一个候选键(主键或唯一标识符)的属性。
-
非主属性:不包含在任何候选键中的属性。
例如,在 学生表(学号, 姓名, 年龄) 中,学号是主键,那么姓名和年龄就是非主属性。
传递依赖
传递依赖指的是一个非主属性间接地依赖于主键。
具体来说:
-
存在
A -> B(B 函数依赖于 A) -
并且
B -> C(C 函数依赖于 B) -
但 B 不依赖于 A(或者说,B 不是 A 的子集,且 A 不依赖于 B)
-
那么,就存在
A -> C的传递依赖。
在数据库表中,这意味着:
主键 -> 非主属性B -> 非主属性C
第三范式就是要消除这种“主键 -> B -> C”的间接关系,要求 C 必须直接依赖于主键,而不是通过 B。
3. 一个经典例子:学生信息表
让我们通过一个例子来一步步地规范化到第三范式。
初始表 (不符合1NF,但我们先假设它符合)
假设我们有一个 学生选课表:
| 学号 | 姓名 | 系名 | 系主任 | 课程号 | 课程名称 | 成绩 |
|---|---|---|---|---|---|---|
| 001 | 张三 | 计算机系 | 李主任 | C01 | 数据库 | 90 |
| 001 | 张三 | 计算机系 | 李主任 | C02 | 数据结构 | 85 |
| 002 | 李四 | 物理系 | 王主任 | C01 | 数据库 | 88 |
| 003 | 王五 | 计算机系 | 李主任 | C03 | 计算机网络 | 92 |
第一步:判断是否符合第二范式(2NF)
-
候选键(主键):
(学号, 课程号)。因为需要这两个字段才能唯一确定一条记录(特别是成绩)。 -
非主属性:
姓名、系名、系主任、课程名称、成绩。
检查是否存在部分依赖:
-
成绩完全依赖于主键(学号, 课程号)。 -
姓名和系名只依赖于学号,而与课程号无关。这就是部分依赖! -
同样,
课程名称只依赖于课程号,而与学号无关。这也是部分依赖!
所以,该表不符合第二范式。
第二步:分解到第二范式(2NF)
为了消除部分依赖,我们将其分解为三个表:
- 学生表 Student
| 学号 | 姓名 | 系名 | 系主任 |
|---|---|---|---|
| 001 | 张三 | 计算机系 | 李主任 |
| 002 | 李四 | 物理系 | 王主任 |
| 003 | 王五 | 计算机系 | 李主任 |
- 课程表 Course
| 课程号 | 课程名称 |
|---|---|
| C01 | 数据库 |
| C02 | 数据结构 |
| C03 | 计算机网络 |
- 选课关系表 SC
| 学号 | 课程号 | 成绩 |
|---|---|---|
| 001 | C01 | 90 |
| 001 | C02 | 85 |
| 002 | C01 | 88 |
| 003 | C03 | 92 |
现在,每个非主属性都完全依赖于其所在表的主键,满足了第二范式。
第三步:判断是否符合第三范式(3NF)
现在我们重点看 Student 表。
-
主键:
学号 -
非主属性:
姓名、系名、系主任
检查是否存在传递依赖:
-
学号->系名(一个学生只能属于一个系) -
系名->系主任(一个系只有一个系主任) -
但是,
系主任并不直接依赖于学号,而是通过系名间接依赖。 -
因此,存在传递依赖:
学号->系名->系主任
这会导致什么问题?(更新异常)
-
数据冗余:计算机系有1000个学生,“李主任”就要重复存储1000次。
-
更新异常:如果计算机系换主任了,必须修改所有属于计算机系的学生记录,漏改一条就会导致数据不一致。
-
插入异常:新成立一个“化学系”,还没有招生,就无法将系和系主任的信息存入数据库,因为
学号主键不能为空。 -
删除异常:如果某个系的学生全部毕业了,删除这些学生记录的同时,这个系和系主任的信息也会被丢失。
第四步:分解到第三范式(3NF)
为了消除传递依赖,我们将 系主任 从 Student 表中分离出去。
- 学生表 Student (3NF)
| 学号 | 姓名 | 系名 |
|---|---|---|
| 001 | 张三 | 计算机系 |
| 002 | 李四 | 物理系 |
| 003 | 王五 | 计算机系 |
- 系列表 Department (3NF)
| 系名 | 系主任 |
|---|---|
| 计算机系 | 李主任 |
| 物理系 | 王主任 |
- 课程表 Course (已经是3NF)
| 课程号 | 课程名称 |
|---|
- 选课关系表 SC (已经是3NF)
| 学号 | 课程号 | 成绩 |
|---|
现在,每个表中的所有非主属性都直接且完全地依赖于主键,不存在任何传递依赖。我们成功达到了第三范式!
4. 总结与记忆口诀
-
第一范式(1NF):属性不可分(原子性)。
-
第二范式(2NF):消除部分依赖(非主属性必须完全依赖于主键)。
-
第三范式(3NF):在2NF基础上,消除传递依赖(非主属性必须直接依赖于主键)。
一个非常流行的记忆口诀是:
“每一个非主属性,都必须直接依赖于主键,直接依赖于主键,直接依赖于主键。”
5. 第三范式的优缺点
优点:
-
最大程度地减少了数据冗余。
-
避免了更新、插入、删除异常,数据一致性更好。
缺点:
-
表数量增多,简单的查询可能变得复杂,需要更多的
JOIN操作。 -
在某些需要极高查询性能、而更新较少的场景(如数据仓库),有时会故意违反第三范式(反规范化),用空间换时间。
204

被折叠的 条评论
为什么被折叠?



