数据库设计三范式(NF)之第三范式极简说明
一句话核心思想
第三范式就是:消除“间接依赖”,表中不能有“子关系”。
更专业一点说:在满足第二范式的基础上,确保表中的每一列都直接依赖于主键,而不能依赖于其他非主键列(即不能存在传递依赖)。
用一个生动的例子来解释
假设我们有一张 学生表,记录学生、他们的学院以及学院的详细信息。
| 学号 (主键) | 姓名 | 所在学院 | 学院院长 | 学院地点 |
|---|---|---|---|---|
| 2023001 | 张三 | 计算机学院 | 李教授 | 科技楼A座 |
| 2023002 | 李四 | 计算机学院 | 李教授 | 科技楼A座 |
| 2023003 | 王五 | 外国语学院 | 张教授 | 人文楼B座 |
这张表有什么问题?(它违反第三范式)
-
冗余重复:
-
张三是计算机学院的,李四也是。那么“计算机学院”的院长和地点信息就被重复存储了多次。如果一个学院有几千个学生,这个信息就会被重复几千次!
-
-
更新异常:
-
如果计算机学院换院长了,新任院长是“王教授”。我们必须找到所有
所在学院 = 计算机学院的记录,一条一条地去修改学院院长字段。万一漏改了一行,就会导致数据不一致(有的记录是李教授,有的记录是王教授)。
-
-
插入异常:
-
学校新成立了一个“法学院”,已经任命了院长“赵教授”,地点在“社科楼C座”。但是,如果还没有学生被录入这个学院,我们就无法把这个新学院的信息插入到这张表里。因为
学号主键不能为空。
-
-
删除异常:
-
如果学生“李四”毕业了,我们从表中删除了他的记录。假如他恰好是计算机学院的最后一个学生,那么删除这条记录的同时,我们也会意外地丢失“计算机学院”的院长和地点信息。
-
为什么会这样?
因为这张表里存在“间接依赖”,也叫“传递依赖”。我们来分析一下依赖关系:
-
学号 (主键) -> 决定了
姓名和所在学院。 ✅ (这没问题) -
学号 (主键) ->
所在学院-> 决定了学院院长和学院地点。 ❌ (问题在这里!)
学院院长和学院地点并不是直接由学号决定的,而是由所在学院这个非主键字段决定的。学号决定了所在学院,所在学院又决定了学院院长,这就形成了一个传递链。
这种“一个非主键字段决定了其他非主键字段”的情况,就是违反第三范式的根源。
如何改造?(使其符合第三范式)
核心操作:继续拆表!把“子关系”独立出去。
我们把上面那张表拆成两张表:
1. 学生表 (核心信息:学生和学院的从属关系)
| 学号 (主键) | 姓名 | 所在学院 (外键) |
|---|---|---|
| 2023001 | 张三 | 计算机学院 |
| 2023002 | 李四 | 计算机学院 |
| 2023003 | 王五 | 外国语学院 |
2. 学院表 (专门管理学院的详细信息)
| 学院名称 (主键) | 学院院长 | 学院地点 | |
|---|---|---|---|
| 计算机学院 | 李教授 | 科技楼A座 | |
| 外国语学院 | 张教授 | 人文楼B座 | |
| 法学院 | 赵教授 | 社科楼C座 | (新学院可以独立添加了!) |
改造后的好处:
-
数据冗余彻底消除:每个学院的信息(院长、地点)只存储一次,而不是随着学生数量重复存储。
-
避免更新异常:计算机学院换院长,只需在
学院表里修改一条记录即可。 -
避免插入异常:新成立的“法学院”可以直接添加到
学院表,完全不受是否有学生的影响。 -
避免删除异常:即使计算机学院的所有学生都毕业了,其信息依然安全地保存在
学院表中。
总结:如何判断和满足第三范式?
-
第一步:确保你的表已经满足了第二范式。
-
第二步:检查表中的每一个非主键字段,问自己两个问题:
a. “这个字段是直接依赖于主键吗?”
b. “这个字段会不会依赖于另一个非主键字段?” -
第三步:如果发现存在这种“传递依赖”(即字段A依赖于主键,但字段B又依赖于字段A),就把这些间接依赖的字段(B)拆出去,建立一张新表,让决定它们的那个字段(A)成为新表的主键。
一个简单的记忆口诀
-
第一范式(1NF):列不可再分。(保证原子性)
-
第二范式(2NF):消除部分依赖。(非主键字段必须完全依赖整个主键)
-
第三范式(3NF):消除传递依赖。(非主键字段之间不能有依赖关系)
最终记住那个简单的比喻:
-
违反2NF:像一个员工同时向两个部门经理汇报工作,职责不清。
-
违反3NF:像在员工表里不仅记录了员工的部门,还记录了部门的预算、部门的规章制度等。这些信息本应属于部门表,而不是员工表。

浙公网安备 33010602011771号