数据库范式小笔记
深炭夜里的一点青光:把 1NF / 2NF / 3NF 讲成人话
范式 = 设计表时少存重复、少改漏
为啥要范式
同一句话别存很多份
假如一个表里面,「5 号楼在东门」如果写在一百行里(被使用了100次),楼一搬家就要改一百次------改漏一行,数据就打架
办法:拆表,让一句话只出现一次
1NF:一格一个意思
| 例子 | |
|---|---|
| 不行 | 爱好 = 球,歌,游戏(一格打包) |
| 可以 | 一行一个爱好,或单独一张爱好表 |
人话:格子里别打包
没有范式时(很烂的一张表)
| 学号 | 姓名 | 课程 | 学分 | 学院 | 学院办公楼 |
|---|---|---|---|---|---|
| 01 | 小明 | 高数,英语 | 4,2 | 计院 | A楼 |
| 01 | 小明 | 高数,英语 | 4,2 | 计院 | A楼 |
问题一大堆:
- 一门课改学分,要改很多行
- 姓名、学院重复存储
- 一格里塞了多门课......
1NF:格子里只能是「原子」值
一格只放一个值,不能写成 高数,英语。
| 学号 | 姓名 | 课程 | 学分 | 学院 | 办公楼 |
|---|---|---|---|---|---|
| 01 | 小明 | 高数 | 4 | 计院 | A楼 |
| 01 | 小明 | 英语 | 2 | 计院 | A楼 |
- 满足 1NF:每格一个意思
- 还有问题:小明、计院仍写了两遍(这是后面 2NF / 3NF 要管的)
2NF:必须靠**「整个」**主键
这一列对应的元素能且只能由全部的主键推理出来
,这一列要由 全部主键 推出来,不能只由主键的一部分推出来
非主键列要由 整个主键 决定,不能只靠主键的 一半
啥时候容易挂
主键是两列拼的,比如 (学号, 课程):
| 学号 | 课程 | 姓名 | 学分 |
|---|---|---|---|
| 01 | 高数 | 小明 | 4 |
审一下:
姓名→ 只靠 学号 → 违规学分→ 只靠 课程 → 违规
怎么拆
学生表
| 学号 | 姓名 |
|---|---|
| 01 | 小明 |
课程表
| 课程 | 学分 |
|---|---|
| 高数 | 4 |
选课表
| 学号 | 课程 |
|---|---|
| 01 | 高数 |
选课表只留真正属于「这次选择」的东西(比如以后加 成绩)。
小提示
主键 只有一列 (学号 / id)时,一般 自动满足 2NF------没有「一半」可以部分依赖。
3NF:别靠「中间商」转推
非主键列要由主键 直接 决定;若由「另一个非主键列」推出来,就拆走
3NF 管的是:非主键字段之间,也别互相决定
表里已经有 A,而 B 其实是由 A 推出来的 → B 不该再放这张表
有病的表(假设已过 2NF)
主键只有 学号(一列,所以 2NF 不太用操心):
| 学号 | 姓名 | 学院 | 学院办公楼 |
|---|---|---|---|
| 01 | 小明 | 计院 | A楼 |
| 02 | 小红 | 计院 | A楼 |
| 03 | 小刚 | 软院 | B楼 |
问:学院办公楼 跟谁有关?
- 不是直接跟学号有关
- 是跟 学院 有关:计院 → A楼,软院 → B楼
也就是:学号 → 学院 → 学院办公楼
办公楼是「隔了一层」推出来的。
计院搬楼的话,小明、小红两行都要改 → 又重复又容易漏
这就是违反 3NF
3NF 怎么治?再拆!
学生表(只留直接跟学生有关的)
| 学号 | 姓名 | 学院 |
|---|---|---|
| 01 | 小明 | 计院 |
| 02 | 小红 | 计院 |
| 03 | 小刚 | 软院 |
学院表(学院自己的属性放这里)
| 学院 | 办公楼 |
|---|---|
| 计院 | A楼 |
| 软院 | B楼 |
办公楼只存一次。要改,改学院表一行。
这就是 3NF
口诀(和 2NF 并排记)
| 问什么 | 违规长什么样 | |
|---|---|---|
| 2NF | 是不是只靠主键的一部分? | 选课表里塞姓名、学分 |
| 3NF | 是不是靠另一个非主键列推出来的? | 学生表里塞学院办公楼 |
3NF 再缩一句:
非主键列之间,不要互相推出对方。