我们可以把数据库的“范式(Normal Forms)”理解为一套整理房间(数据表)的家规。
为了避免数据乱成一团(冗余)或导致更新困难(异常),我们需要层层递进地遵守这些规则。
1NF(第一范式):属性不可再分
【通俗理解】:“原子化”——每个格子里只能装一样东西。
- 反面教材:你在一个“联系方式”格子里填了“电话:138xxx,微信:abc”。
- 1NF 要求:必须拆开。一个格子就是电话,一个格子就是微信。
- 核心理念:数据库不认“大礼包”,字段必须是最基本的单位。
2NF(第二范式):消除部分依赖
【通俗理解】:“各司其职”——表里的内容必须完全跟着“带头的(主键)”走。
- 背景:这通常发生在“复合主键”(两个字段共同当老大)的情况下。
- 反面教材:有一张表主键是 [学生ID + 课程ID],里面还有字段 [学生姓名]。
- 问题在于:姓名只跟 学生ID 有关,跟 课程ID 没关系。
- 2NF 要求:把表拆开。学生信息一张表,选课关系一张表。
- 核心理念:非主键字段不能只听其中一个“老大”的话,要听就得听全套。
3NF(第三范式):消除传递依赖
【通俗理解】:“拒绝间谍”——禁止通过“中间人”来拉关系。
- 反面教材:表主键是 [学生ID],字段有 [学院ID] 和 [学院电话]。
- 问题在于:学院电话 是跟着 学院ID 走的,而 学院ID 才是跟着 学生ID 走的。
- 3NF 要求:把 学院电话 挪走,单独存一张学院信息表。
- 核心理念:非主键字段必须直接依赖主键,不能通过其他字段“间接”依赖。
BCNF(鲍伊斯-科德范式):加强版 3NF
【通俗理解】:“主键也得查岗”——连主键里的成员也不能有猫腻。
- 核心:如果你的主键由多个字段组成,主键内部的字段之间也不能有依赖关系。
4NF(第四范式):消除多值依赖
【通俗理解】:“不许乱点鸳鸯谱”——一张表里别存两种没关系的“多对多”。
- 反面教材:一张表存 [老师、课程、兴趣爱好]。
- 张老师教《数学》和《物理》,张老师喜欢“下棋”和“游泳”。
- 你会发现表里会出现:张老师-数学-下棋、张老师-物理-下棋、张老师-数学-游泳……数据爆炸了。
- 4NF 要求:把 [老师-课程] 和 [老师-爱好] 拆成两张独立的表。
- 核心理念:两件没关联的事儿,别强行凑在一张表里。
总结口诀
- 1NF:属性要独立(原子性)。
- 2NF:不要偏心(完全依赖主键)。
- 3NF:不要中间商(消除传递依赖)。
- 4NF:不要乱组合(消除多值依赖)。
实际开发中,通常做到 3NF 就足够应对 90% 的场景了,过度范式化会导致查询时需要关联(Join)太多表,反而降低性能。