数据库三大范式是关系型数据库设计的基本规则,旨在减少数据冗余、确保数据完整性。
分别是原子性、全依赖、无传递
第一范式(1NF):原子性
定义:
数据表的每一列都是不可分割的原子数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。
例如:
| 学生 ID | 姓名 | 课程 |
|---|---|---|
| 001 | 张三 | 数学,英语,物理 |
这样就违背了原子性,某个属性有多个值。
| 学生 ID | 姓名 | 课程 | 课程 |
|---|---|---|---|
| 001 | 张三 | 数学 | 英语,物理 |
这样不止是违背了多个值的情况还有重复的属性。
修正:
拆分为多条记录,每个课程单独一行:
| 学生 ID | 姓名 | 课程 |
|---|---|---|
| 001 | 张三 | 数学 |
| 001 | 张三 | 英语 |
| 001 | 张三 | 物理 |
第二范式(2NF):全依赖
定义:
满足 1NF,且所有非主属性完全依赖于主键(而非部分依赖)。
反例:
订单表(订单 ID,客户 ID,客户姓名,商品 ID,商品名称,数量)
主键:(订单ID, 商品ID)
部分依赖:客户姓名依赖于客户 ID,而非整个主键。
问题:
插入异常:新增客户但无订单时无法插入。
更新异常:修改客户姓名需更新多条记录。
修正:
拆分为两个表:
订单详情表(订单 ID,商品 ID,数量)
主键:(订单ID, 商品ID)
客户表(客户 ID,客户姓名)
主键:客户ID
第三范式(3NF):消除传递依赖
定义:
满足 2NF,且所有非主属性不依赖于其他非主属性(即消除传递依赖)。
反例:
| 学生 ID(主键) | 学院 ID | 学院名称 | 院长姓名 | 学生姓名 |
|---|---|---|---|---|
| 001 | 01 | 计算机学院 | 王教授 | 张三 |
| 002 | 01 | 计算机学院 | 王教授 | 李四 |
| 003 | 02 | 文学院 | 李教授 | 王五 |
问题分析:
主键是学生ID(单列主键,满足 1NF 和 2NF)。
非主属性之间存在依赖关系:学院名称和院长姓名依赖于学院ID,而学院ID本身是依赖于学生ID的非主属性。
形成传递依赖链:学生ID → 学院ID → 学院名称/院长姓名(即学院名称和院长姓名通过学院ID间接依赖于主键学生ID)。
导致的问题:
冗余:同一学院的学生记录会重复存储学院名称和院长姓名(如 001 和 002 都重复 “计算机学院”“王教授”)。
更新异常:若 “计算机学院” 改名为 “人工智能学院”,需修改所有该学院学生的记录,容易遗漏。
修正(符合 3NF): 拆分表以消除传递依赖,确保非主属性只直接依赖于主键:
| 学生 ID(主键) | 学院 ID | 学生姓名 |
|---|---|---|
| 001 | 01 | 张三 |
| 002 | 01 | 李四 |
| 003 | 02 | 王五 |
| 学院 ID(主键) | 学院名称 | 院长姓名 |
|---|---|---|
| 01 | 计算机学院 | 王教授 |
| 02 | 文学院 | 李教授 |
2NF 与 3NF 的核心区别(通过例子对比):
| 范式 | 核心问题 | 依赖关系类型 | 例子场景 |
|---|---|---|---|
| 2NF | 非主属性“部分依赖”于主键 | 针对复合主键:非主属性仅依赖主键的某一列(而非全部) | 订单详情表中,“商品名称”仅依赖“商品ID”(复合主键为“订单ID + 商品ID”) |
| 3NF | 非主属性“传递依赖”于主键 | 针对非主属性之间:非主属性A依赖非主属性B,非主属性B依赖主键 | 学生表中,“院长姓名”依赖“学院ID”,“学院ID”依赖“学生ID”(主键) |
本文作者:haotian
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!