知识点:关于数据库范式比较好理解的解释

19 阅读10分钟

了解基本术语

一、核心「键」术语对照表

术语通俗定义大白话速记关键规则
超键能唯一确定一行数据的字段/字段组合,可带多余字段能找人就行,带不带累赘不管只要求唯一性,不要求精简
候选键最精简的超键,去掉任意一个字段就无法唯一确定数据精干小分队,刚好能找人是主键的候选人,一张表可以有多个
主键从候选键里人为选定的、官方唯一标识表的官方身份证号一张表只能有一个,不能为空、不能重复
外键A表中的字段,刚好是B表的主键两张表的联姻凭证用来关联表,保证数据对应关系合法
主属性所有候选键里出现过的字段有资格当主键的「领导层」不是只有主键字段才算,所有候选键包含的字段都是
非主属性从未出现在任何候选键里的字段纯纯的「小弟」只能被别人决定,不能决定别人

二、核心「依赖」术语对照表

术语通俗定义大白话速记对应消除范式
函数依赖确定A就能唯一确定B,记作A→BA能说了算B范式的基础概念
部分函数依赖组合主键里,非主属性只依赖主键的一部分小弟只认半个大哥团队2NF消除
传递函数依赖A→B,B→C,C通过B间接依赖A小弟通过中间商认大哥3NF消除
多值依赖一张表里同时存在两个独立的一对多关系两个不相干的事挤一张表4NF消除

先铺垫:范式到底是啥?

数据库范式,就是设计数据库表的“整洁等级” ,从1NF到4NF,等级越高,表拆得越细,数据重复越少,也越不容易出现“加不进去、删错了、改半天”的奇葩问题。

就像整理书包:

  • 1NF = 把东西都摊开,不揉成一团
  • 2NF = 分课本、文具两个袋子装
  • 3NF = 课本里再分语文袋、数学袋
  • BCNF = 袋子上的标签也不能互相混淆
  • 4NF = 水杯、跳绳这种和课本无关的也单独放

核心原则只有一句话:一张表只说一件事。


1NF(第一范式):每个格子只能放一个东西

核心要求:表中每一列都是不可拆分的“最小单元”,不能一列塞好几个信息。 大白话:每个格子只能放一个东西,不能打包塞一堆。

❌ 不符合1NF的反面教材:

学号个人信息
001张三,男,一班

“个人信息”列同时装了姓名、性别、班级,还能继续拆,所以不符合1NF。

✅ 符合1NF的正确打开方式:

学号姓名性别班级
001张三男一班

1NF是最基础的门槛,连这个都达不到,后面的都免谈。


2NF(第二范式):小弟必须认整个大哥团队,不能只认一个

先补个常识:主键就是能唯一确定一行数据的“身份证”,可以是一个字段,也可以是几个字段组队。

核心要求:在1NF基础上,所有非主键字段,必须完全依赖整个主键,不能只依赖主键的一部分。 大白话:主键如果是“双人组合”,那每个小弟都必须认整个组合,不能只跟组合里一个人混。

❌ 不符合2NF的反面教材(成绩表,主键是「学号+课程号」组队):

学号课程号姓名课程名分数
001101张三数学90
002101李四数学85

问题出在哪?

主键是「学号+课程号」两个人组队,但:

  • 「姓名」只靠「学号」就能确定,跟课程号没关系 → 只认了半个大哥
  • 「课程名」只靠「课程号」就能确定,跟学号没关系 → 也只认了半个大哥
  • 只有「分数」必须「学号+课程号」一起才能确定 → 认了整个团队

会惹什么麻烦?

  1. 冗余爆炸:数学这门课100个学生选,“数学”俩字要重复存100遍
  2. 插不进去:新开一门课,还没人选,这门课的信息根本插不进去(主键里学号不能为空)
  3. 删没了:某门课所有人都退课了,这门课本身的信息也跟着被删掉了
  4. 改累死:把“数学”改成“高等数学”,得改100条记录

✅ 怎么改符合2NF?拆表! 一张表拆成三张,每张只干一件事:

  1. 学生表(学号,姓名)→ 主键:学号
  2. 课程表(课程号,课程名)→ 主键:课程号
  3. 成绩表(学号,课程号,分数)→ 主键:学号+课程号

现在每张表里,非主键字段都完全依赖主键,符合2NF。


3NF(第三范式):小弟只能直接认大哥,不能认小弟的小弟

核心要求:在2NF基础上,消除传递依赖——非主键字段不能依赖其他非主键字段,必须直接依赖主键。 大白话:小弟只能直接认大哥,不能通过另一个小弟间接认大哥,中间不许有“中间商”。

❌ 不符合3NF的反面教材(学生表,主键是「学号」):

学号姓名班级班主任
001张三一班王老师
002李四一班王老师

问题出在哪?

「班主任」不直接依赖学号,而是依赖「班级」,「班级」才依赖学号。 相当于:学号 → 班级 → 班主任,中间隔了一层,这就是“传递依赖”。

会惹什么麻烦?

和2NF的麻烦一模一样:

  • 一班50个学生,“王老师”重复存50遍
  • 新班级没学生,班主任信息插不进去
  • 学生都毕业,班主任信息也没了
  • 换班主任得改50条记录

✅ 怎么改符合3NF?继续拆!

  1. 学生表(学号,姓名,班级号)→ 主键:学号
  2. 班级表(班级号,班主任)→ 主键:班级号

现在所有非主键字段都直接依赖主键,没有中间商赚差价,符合3NF。

划重点:3NF是业界最常用的范式,绝大多数业务系统设计到3NF就够用了。


BCNF(巴斯范式):连大哥内部也不能互相管

这是最容易懵的,也是你重点想听的,咱们掰开揉碎讲。

先回忆3NF的漏洞

3NF的规矩是:只管“小弟”(非主键字段),不管“大哥团队”(主键里的字段)内部。 3NF说“小弟不能依赖小弟”,但没说“大哥团队里,一个大哥不能管另一个大哥”。

BCNF就是把这个漏洞补上了。

核心要求:只要某个字段能决定别的字段,那它自己必须是完整的主键(候选键)。 大白话:不管是大哥还是小弟,只要你能说了算,你就必须是“一把手”,不能是二把手就能管另一个二把手。

举个生活化的例子:社团报名表

先定规则:

  1. 每个社团只有1个指导老师
  2. 每个老师只指导1个社团
  3. 一个学生可以报多个社团,一个社团有多个学生

❌ 符合3NF,但不符合BCNF的表(主键是「学生+社团」):

学生社团指导老师
张三篮球社李老师
李四篮球社李老师
张三动漫社王老师

先讲:为什么它符合3NF?

这张表里,能当主键的组合有两个:

  • 「学生 + 社团」→ 能确定老师
  • 「学生 + 老师」→ 能确定社团

也就是说,三个字段都是“有资格当主键的人”(主属性),没有纯小弟(非主属性) 。 而3NF管的是“非主属性不能依赖非主属性”,既然连非主属性都没有,那它天然符合3NF。

但它有大问题:

  1. 插不进去:我想新成立“围棋社”,指定“赵老师”当指导,但还没人报名。根本插不进去——因为主键里的“学生”不能为空。
  2. 改累死:篮球社换指导老师了,得把所有报篮球社的学生记录都改一遍。
  3. 删没了:篮球社的学生都退社了,篮球社和李老师的对应关系也跟着没了。

病根在哪?

「社团」能决定「指导老师」,但「社团」自己不是一个完整的主键(主键是学生+社团组队)。 它只是大哥团队里的一员,却能决定另一个大哥成员——这就是BCNF禁止的。

✅ 怎么改符合BCNF?拆成两张表:

  1. 社团表(社团,指导老师)→ 主键:社团
  2. 报名表(学生,社团)→ 主键:学生+社团

现在再看:

  • 社团表里,社团是主键,老师依赖社团 → 能决定别人的,自己就是完整主键
  • 报名内外,学生+社团是主键,没有其他字段 → 没问题

所有“能说了算”的字段,自己都是完整的一把手,完美解决所有异常。

一句话记住3NF和BCNF的区别

  • 3NF:小弟不能依赖小弟(管住底层)
  • BCNF:大哥内部也不能互相依赖(管住高层)
  • 更简单的记法:一张表里,只要“A能推出B”,A就必须是整张表的主键。

4NF(第四范式):一张表不能有两个独立的“一对多”

核心要求:在BCNF基础上,消除多值依赖——一张表里不能同时有两个互相独立的“一对多”关系。 大白话:一张表只讲一个“一对多”,两个没关系的一对多不能放一起,不然会交叉繁殖出一堆冗余数据。

❌ 不符合4NF的反面教材:

学生兴趣特长
张三篮球画画
张三篮球钢琴
张三游泳画画
张三游泳钢琴

一个学生可以有多个兴趣,也可以有多个特长,兴趣和特长之间半毛钱关系都没有。 张三有2个兴趣、2个特长,结果存了4条记录(2×2)。如果有3个兴趣、4个特长,就要存12条,冗余爆炸。

✅ 怎么改符合4NF?拆!

  1. 学生兴趣表(学生,兴趣)→ 管兴趣这一个一对多
  2. 学生特长表(学生,特长)→ 管特长这一个一对多

各管各的,互不干扰,冗余立刻消失。


最后一张表总结

范式核心目标大白话记忆
1NF字段原子性每个格子只放一个东西
2NF消除部分依赖小弟必须认整个大哥团队
3NF消除传递依赖小弟只能直接认大哥
BCNF消除主属性内部依赖能说了算的,必须是完整大哥
4NF消除多值依赖一张表只能有一个“一对多”

实际开发小建议

  • 绝大多数业务场景,3NF就够用了,兼顾整洁和查询性能。
  • 要求高一点可以到BCNF,进一步减少数据异常。
  • 4NF用得很少,一般只有数据仓库、极端去冗余场景才会用到。
  • 范式不是越高越好:表拆得越多,查询时连表就越多,性能会下降。有时候为了查询快,还会故意“反范式”(加一点冗余字段)。