核心前置概念
1. 候选码(主键):能唯一标识整条记录的字段/字段组合
2. 主属性:出现在任意候选码中的字段
3. 非主属性:不在候选码里的普通业务字段
4. 函数依赖 X→Y:知道X就能唯一确定Y
5. 存在字段不能被完整主键唯一确定:不属于范式问题,表主键不合法,不满足关系数据库

一、1NF 第一范式(原子性)
1. 官方标准定义
数据表中所有字段都是原子的、不可再拆分,不允许多值、嵌套、组合字段。
2. 违规示例
学生表:(学号, 姓名, 联系方式)
数据:(1001, 张三, "138xxx;139xxx")
联系方式存储多个手机号,可拆分,违反1NF。
3. 合规改造
拆分为单行单值,一列只存一个数据。
一句话记忆
1NF:单元格不能分家
二、2NF 第二范式(消除:非主属性 部分依赖 候选码)
1. 官方精准定义
在满足1NF基础上:消除所有非主属性对候选码的部分函数依赖。
2. 人话解释
如果是复合主键,所有普通字段(非主属性),必须依赖完整主键,不能只靠主键其中一部分就能推导出来。
单字段主键天然满足2NF,只有复合主键才会违反2NF。
3. 纯净违规案例(只违反2NF,不牵扯3NF/BCNF)
订单明细表
复合候选码:订单ID + 商品ID
字段:订单ID、商品ID、订单时间、商品名称、购买数量
主属性:订单ID、商品ID
非主属性:订单时间、商品名称、购买数量
函数依赖分析
1. 订单ID → 订单时间(只依赖主键一部分)
2. 商品ID → 商品名称(只依赖主键一部分)
3. (订单ID+商品ID) → 购买数量(完全依赖)
违规核心
非主属性被部分主属性推导 = 违反2NF
这就是所有“部分依赖”的标准本质:普通字段,不需要整张主键,只靠主键片段就能确定。
4. 2NF 合规拆分
订单表(订单ID,订单时间)
商品表(商品ID,商品名称)
订单详情表(订单ID,商品ID,购买数量)
一句话记忆
2NF:非主属性,不许偷懒只靠一半主键
三、3NF 第三范式(消除:非主属性 传递依赖 候选码)
1. 官方精准定义
在满足2NF基础上:消除所有非主属性对候选码的传递函数依赖。
2. 人话解释
所有普通字段(非主属性),只能直接依赖主键,不能通过另一个普通字段间接依赖主键。
约束范围:只管非主属性,不管主属性。
3. 纯净违规案例(✅2NF ❌3NF,无任何2NF/BCNF问题)
支付渠道表
主键:渠道ID(单主键,天然满足2NF)
字段:渠道ID、渠道名称、结算ID、结算名称
函数依赖
渠道ID → 结算ID
结算ID → 结算名称
传递链:渠道ID → 结算ID → 结算名称
违规核心
结算名称是非主属性,不直接依赖主键,依赖另一个非主属性,传递依赖,违反3NF。
4. 3NF 合规拆分
渠道表(渠道ID,渠道名称,结算ID)
结算字典表(结算ID,结算名称)
一句话记忆
3NF:非主属性之间,不许互相依赖
四、BCNF 巴斯-科德范式
1. 官方精准定义
在满足3NF基础上:任何非平凡函数依赖 X→Y,X 必须是超码(候选码)。
2. 人话终极翻译
谁能决定别人,谁就必须是主键。
3. 2NF/3NF/BCNF 本质层级区别(你最需要的总结)
- 2NF 只查:非主属性(有没有部分依赖)
- 3NF 只查:非主属性(有没有传递依赖)
- BCNF 全查:主属性 + 非主属性(堵死所有依赖漏洞)
重点:3NF 放行了「主属性之间的非法依赖」,BCNF 专门干掉它
4. 教科书零漏洞案例(✅2NF ✅3NF ❌BCNF)
关系:STJ(学生S, 教师T, 课程J)
业务规则:
1. 一个老师只教一门课:T→J
2. 学生选某个老师,就确定课程;学生选某课程,就确定老师
3. 双候选码:(S,T)、(S,J)
属性判定
所有字段 S、T、J 全部是主属性,无任何非主属性
逐层范式校验(绝对零错误)
✅ 满足2NF:没有非主属性,不存在部分依赖
✅ 满足3NF:没有非主属性,不存在传递依赖
❌ 违反BCNF:存在依赖 T→J
解析:T 是主属性,但 T 不是候选码,却能决定其他字段。违背「能决定别人的必须是主键」。
5. BCNF 合规拆分
TJ(教师T, 课程J) 主键:T
ST(学生S, 教师T) 主键:S+T
一句话记忆
BCNF:所有决定者,必须是主键
五、4NF 第四范式(消除独立多值依赖)
1. 官方精准定义
在满足BCNF基础上:消除所有不包含候选码的非平凡多值依赖。
2. 人话终极翻译
一张表内,多组互相无关的「一对多关系」,必须拆分独立表。
前面 2NF/3NF/BCNF 解决的都是函数依赖(一对一、多对一)问题;4NF 专门解决多值依赖(一对多)的数据冗余问题。
3. 核心前置:多值依赖通俗理解
多值依赖:已知X,能对应一组多个Y,且Y的取值和表中其他字段无关,记作
- 平凡多值依赖:无需处理(字段互相包含)
- 非平凡多值依赖:需要4NF强制拆分,杜绝冗余
4. 纯净违规案例(✅2NF ✅3NF ✅BCNF ❌4NF)
商户权限配置表(完全满足前三范式+BCNF,仅违反4NF)
表结构:商户ID、支付渠道、支付场景
业务规则:
1. 一个商户可开通多个支付渠道(微信、支付宝、云闪付)
2. 一个商户可适配多个支付场景(扫码支付、小程序支付、H5支付)
3. 支付渠道 和 支付场景 完全互相独立、无任何关联
4. 主键:商户ID(单主键,无任何部分依赖、传递依赖、非法主属性依赖)
违规数据演示
同一商户,两组独立一对多关系,强行混表产生笛卡尔积冗余:
MER001 微信 扫码支付
MER001 微信 小程序支付
MER001 支付宝 扫码支付
MER001 支付宝 小程序支付
多值依赖分析
1. 商户ID ->> 支付渠道
2. 商户ID ->> 支付场景
违规核心:同一主键下,存在两组互相独立的非平凡多值依赖,且不包含候选码,严重违反4NF。
5. 存在的业务问题
- 海量数据冗余:渠道、场景自由组合,数据量成倍爆炸
- 维护异常:新增一个支付场景,需要批量新增所有渠道关联数据
- 脏数据风险:极易出现无效组合,数据一致性极差
6. 4NF 合规拆分改造
表1:商户支付渠道表(单组多值依赖,符合4NF)
(商户ID,支付渠道)
表2:商户支付场景表(单组多值依赖,符合4NF)
(商户ID,支付场景)
改造后:每张表只保留一组多值依赖,彻底消除独立多值依赖冗余,完全满足4NF。
一句话记忆
4NF:无关的一对多,坚决不共存一表
六、终极范式层级对照表
|
范式 |
解决问题 |
约束对象 |
核心口诀 |
|
1NF |
字段可拆分、多值嵌套不原子 |
所有字段 |
原子不可拆 |
|
2NF |
非主属性存在部分函数依赖 |
非主属性 |
不吃半主键 |
|
3NF |
非主属性存在传递函数依赖 |
非主属性 |
不搞间接依赖 |
|
BCNF |
主属性存在非法决定依赖(3NF盲区) |
全部属性(主+非主) |
能决定必是主键 |
|
4NF |
存在独立非平凡多值依赖、笛卡尔积冗余 |
多值属性 |
无关一对多不同表 |
七、避坑总结
1. 只要表里有非主属性被主键片段推出 → 一定违反2NF,没资格谈BCNF
2. 3NF只管普通字段传递问题,完全不管主属性
3. BCNF是真正的“完美3NF”,堵死所有隐性依赖漏洞
4. 4NF 专门解决高维多值业务冗余问题(权限、标签、配置类表必备)
5. 开发实战:常规业务表做到3NF/BCNF即可,多标签、多配置、多维度一对多场景必须上4NF,杜绝数据爆炸

