MySQL 的三大范式详细介绍_mysql 第二范式
文章目录
-
-
- 1、第一范式(1NF):原子性
- 2、第二范式(2NF):消除部分依赖
- 3、第三范式(3NF):消除传递依赖
- 4、三大范式总结
- 4、如何判断数据库设计是否符合第三范式?
-
- 1)确认已满足前两范式
- 2、检查是否存在“传递依赖”
- 3、示例分析
-
- 反例(违反3NF)
- 正例(符合3NF)
- 4、常见误区与注意事项
- 5、判断是否符合第三范式的核心流程:
-
MySQL(关系型数据库)的三大范式是数据库设计的基本准则,用于指导如何合理组织表结构,目的是减少数据冗余和保证数据一致性。遵循范式可以让数据库设计更严谨、维护更高效。
1、第一范式(1NF):原子性
核心要求:表中所有字段的值都必须是不可分割的原子值(即最小单位,不能再拆分)。
解读:
- 不能有复合字段(如“地址”字段不能同时存储“省+市+区”,需拆分为单独字段)。
- 不能有重复的列或多值字段(如“电话”字段不能存储多个号码,应拆分为多行或单独表)。
反例(不满足1NF):
正例(满足1NF):
2、第二范式(2NF):消除部分依赖
前提:必须先满足第一范式(1NF)。
核心要求:表中非主键字段必须完全依赖于整个主键,而不能只依赖于主键的一部分(针对复合主键)。
解读:
- 若表的主键是单一字段(如
id
),则自动满足2NF(因为没有“部分依赖”的可能)。 - 若主键是复合主键(如
(student_id, course_id)
),则其他字段(如score
、student_name
)必须依赖于整个(student_id, course_id)
,而不能只依赖于student_id
(如student_name
只依赖student_id
,属于部分依赖,需拆分)。
反例(不满足2NF):
| student_id(主键) | course_id(主键) | student_name | score | (复合主键:student_id+course_id)
|-------------------|------------------|--------------|-------|
| 101 | 201 | 李四 | 90 | (student_name 只依赖 student_id,属于部分依赖)
正例(满足2NF):
-
拆分出学生表(独立存储学生信息):
student_id(主键) student_name 101 李四 -
成绩表(只保留依赖于复合主键的字段):
student_id(主键) course_id(主键) score 101 201 90
3、第三范式(3NF):消除传递依赖
前提:必须先满足第二范式(2NF)。
核心要求:表中非主键字段之间不能存在依赖关系(即非主键字段必须直接依赖于主键,而不能依赖于其他非主键字段)。
解读:
- 禁止“非主键A → 非主键B”的传递依赖(A和B都不是主键,但B的值由A决定)。
- 需将传递依赖的字段拆分到新表中,通过主键关联。
反例(不满足3NF):
| order_id(主键) | product_id | product_name | price | (product_name和price依赖于product_id,而非主键order_id,形成传递依赖)
|-----------------|------------|--------------|-------|
正例(满足3NF):
-
订单表(只保留与订单直接相关的字段):
order_id(主键) product_id quantity 5001 1001 2 -
商品表(独立存储商品信息):
product_id(主键) product_name price 1001 笔记本电脑 5999
4、三大范式总结
三大范式的核心目标是**“去冗余”**,但并非必须严格遵守:
- 遵循的好处:数据一致性高,更新/删除时不易出现异常(如修改商品名时只需改一次)。
- 灵活处理:实际设计中可能为了查询效率适当保留冗余(如“反范式设计”),需在冗余和性能之间平衡。
简单记忆:
1NF → 字段不可拆;
2NF → 非主键依赖整个主键;
3NF → 非主键之间无依赖。
4、如何判断数据库设计是否符合第三范式?
判断数据库设计是否符合第三范式(3NF),需要基于其核心要求:在满足第二范式(2NF)的前提下,表中的非主键字段必须直接依赖于主键,且不存在非主键字段之间的传递依赖(即“非主键A → 非主键B”的依赖关系)。
具体判断步骤和方法如下:
1)确认已满足前两范式
第三范式是建立在第二范式基础上的,因此需先验证:
- 是否满足1NF:所有字段的值都是不可分割的原子值(无复合字段、多值字段)。
- 是否满足2NF:非主键字段必须完全依赖于整个主键(对复合主键而言,不能只依赖主键的一部分)。
若不满足前两范式,无需判断3NF,需先优化至符合2NF。
2、检查是否存在“传递依赖”
传递依赖的定义:
在表中,若存在 “主键 → 非主键A → 非主键B” 的关系(即B依赖于A,而A依赖于主键),则B传递依赖于主键,违反3NF。
判断方法:
对表中每个非主键字段,问两个问题:
- 这个字段是否直接依赖于主键?(即能否通过主键唯一确定该字段的值?)
- 这个字段是否依赖于表中的其他非主键字段?(即是否存在“非主键A决定非主键B”的情况?)
若存在任何非主键字段依赖于其他非主键字段(而非直接依赖于主键),则违反3NF。
3、示例分析
反例(违反3NF)
假设有一个 orders
表(订单表):
问题:
product_name
和 product_price
依赖于 product_id
(非主键),而 product_id
依赖于主键 order_id
,形成传递依赖(order_id → product_id → product_name
),因此违反3NF。
正例(符合3NF)
拆分后的表结构:
- 订单表(orders):
- 商品表(products):
为什么符合3NF:
- 订单表中,所有非主键字段(
product_id
、quantity
)均直接依赖于主键order_id
。 - 商品表中,所有非主键字段(
product_name
、product_price
)均直接依赖于主键product_id
。 - 不存在非主键字段之间的依赖关系,消除了传递依赖。
4、常见误区与注意事项
-
“直接依赖” vs “间接依赖”:
3NF允许非主键字段“间接关联”主键(如通过外键关联其他表的主键),但不允许在同一张表内通过其他非主键字段间接依赖主键。 -
允许合理的冗余:
实际设计中,为了查询效率可能会保留少量冗余(反范式设计),但这并不影响对3NF的判断——判断是否符合3NF是“是否存在传递依赖”,而非“是否完全无冗余”。 -
复合主键的情况:
即使主键是复合主键(如(A,B)
),只要非主键字段仅依赖于(A,B)
整体,且不依赖于其他非主键字段,仍符合3NF。
5、判断是否符合第三范式的核心流程:
- 确保满足1NF和2NF;
- 检查表中是否存在“非主键A → 非主键B”的传递依赖;
- 若不存在传递依赖,则符合3NF;反之则不符合,需拆分表消除传递依赖。
通过这种方式,可以保证数据的逻辑清晰,减少更新异常(如修改商品名称时,只需在商品表中修改一次,而非所有关联订单表)。