SQL数据库:五大范式(NF)

文章目录


第一范式(1NF)

第一范式是关系型数据库的最基本要求,任何关系型数据库的表都必须满足1NF。

判断标准

  • 原子性:表中的每一列都必须是不可再分的原子值。这意味着一个字段不能包含多个值或重复的组。

样例参考

假设有一个学生选课表,设计如下:

学号 姓名 选修课程
1001 张三 数学, 英语
1002 李四 物理

问题:"选修课程"这一列包含了多个值(数学和英语),违反了原子性原则。

修正方案:将"选修课程"列拆分,确保每行只有一个课程。

学号 姓名 选修课程
1001 张三 数学
1001 张三 英语
1002 李四 物理

现在,每个字段都只包含一个不可分割的值,该表满足第一范式。


第二范式(2NF)

第二范式建立在第一范式的基础上,主要解决数据冗余问题,特别是当表有联合主键时。

判断标准

  • 前提:必须满足第一范式。
  • 核心规则:表中的所有非主键字段必须"完全依赖"于整个主键,而不能只依赖于主键的一部分(即消除"部分依赖")。

样例参考

假设有一个订单详情表,主键是(订单ID, 产品ID)。

订单ID 产品ID 产品名称 购买数量 订单日期
1001 P01 笔记本 2 2023-01-01
1001 P02 钢笔 5 2023-01-01

分析

  • 主键是(订单ID, 产品ID)的组合。
  • "购买数量"依赖于(订单ID, 产品ID),即某个订单里的某个产品买了多少。这是完全依赖。
  • "产品名称"只依赖于"产品ID",与"订单ID"无关。这就是部分依赖。
  • "订单日期"只依赖于"订单ID",与"产品ID"无关。这也是部分依赖。

问题:产品名称和订单日期会大量重复,造成冗余。

修正方案:将表拆分成三个表,消除部分依赖。

  • 订单表:(订单ID, 订单日期)
  • 产品表:(产品ID, 产品名称)
  • 订单详情表:(订单ID, 产品ID, 购买数量)

现在,每个非主键字段都完全依赖于其所在表的主键,该设计满足第二范式。


第三范式(3NF)

第三范式建立在第二范式的基础上,进一步消除数据冗余。

判断标准

  • 前提:必须满足第二范式。
  • 核心规则:表中的所有非主键字段必须"直接依赖"于主键,而不能存在传递依赖。即,非主键字段之间不能有依赖关系。

样例参考

假设有一个员工信息表,主键是员工ID。

员工ID 姓名 部门名称 部门经理
E01 张三 研发部 王经理
E02 李四 市场部 赵经理
E03 王五 研发部 王经理

分析

  • 主键是"员工ID"。
  • "姓名"直接依赖于"员工ID"。
  • "部门名称"也直接依赖于"员工ID"。
  • 但是,"部门经理"并不直接依赖于"员工ID",而是依赖于"部门名称"。因为"研发部"的经理总是"王经理"。
  • 这就形成了传递依赖:员工ID -> 部门名称 -> 部门经理。

问题:如果一个部门的经理更换,需要更新所有该部门员工的信息,非常麻烦且容易出错。

修正方案:将存在传递依赖的字段拆分到新表中。

  • 员工表:(员工ID, 姓名, 部门名称)
  • 部门表:(部门名称, 部门经理)

现在,每个非主键字段都直接依赖于其所在表的主键,消除了传递依赖,该设计满足第三范式。


巴斯-科德范式(BCNF)

BCNF是第三范式的一个增强版本,被认为是"修正的第三范式"。它处理了3NF中未涵盖的一些特殊情况。

判断标准

  • 前提:必须满足第三范式。
  • 核心规则:对于表中的每一个非平凡函数依赖 X -> Y,X 必须是一个超键(即X必须包含候选键)。简单来说,就是所有决定其他字段的字段(决定因素)本身必须是主键或候选键。

样例参考

假设一个仓库管理库存的规则是:一个仓库由一名管理员负责,但一个管理员可以管理多个仓库;一个仓库可以存放多种物品,一种物品也可以存放在多个仓库。

仓库ID 物品ID 管理员
WH1 I001 张三
WH1 I002 张三
WH2 I001 李四

分析

  • 候选键是(仓库ID, 物品ID),因为它们的组合能唯一标识一行。
  • 但是,存在一个依赖关系:仓库ID -> 管理员。一个仓库只对应一个管理员。
  • 这里,"仓库ID"是决定因素,但它本身不是候选键(候选键是组合键)。这违反了BCNF。

问题:如果管理员更换,需要更新该仓库的所有物品记录,造成更新异常。

修正方案:将决定因素不是候选键的依赖关系拆分出去。

  • 仓库管理员表:(仓库ID, 管理员)
  • 库存表:(仓库ID, 物品ID)

现在,每个表中的所有决定因素都是其候选键,该设计满足BCNF。


第四范式(4NF)

第四范式处理的是比函数依赖更复杂的多值依赖问题。

判断标准

  • 前提:必须满足BCNF。
  • 核心规则:表中不能存在非平凡的多值依赖。即,一个实体的多个独立的多值属性不应放在同一张表中。

样例参考

假设一个医生可以在多家医院工作,并且拥有多种专业技能。

医生 医院 技能
张医生 市一医院 外科
张医生 市一医院 骨科
张医生 中心医院 外科
张医生 中心医院 骨科

分析

  • "医院"和"技能"都是"医生"的多值属性。
  • 但"医院"和"技能"是相互独立的。张医生去哪家医院工作,和他会什么技能没有关系。
  • 将它们放在一个表中,会产生大量冗余数据(如示例所示),并且无法独立管理医生和医院、医生和技能的关系。

问题:数据冗余严重,且插入、删除操作会变得复杂。

修正方案:将两个独立的多值依赖拆分成两个表。

  • 医生医院表:(医生, 医院)
  • 医生技能表:(医生, 技能)

现在,每个表只包含一个多值依赖,消除了多值依赖带来的问题,该设计满足第四范式。


总结

在实际的数据库设计中,通常以达到第三范式(3NF)或BCNF为目标,这能在数据规范性和查询性能之间取得很好的平衡。

  • 1NF:基础要求,确保字段原子性。
  • 2NF:解决组合主键导致的冗余。
  • 3NF:解决非主键字段间的依赖导致的冗余,是主流设计目标。
  • BCNF:处理3NF未覆盖的特殊依赖情况,理论更严谨。
  • 4NF:处理独立多值属性的问题,适用于特定场景。

需要注意的是,过度规范化可能会导致查询时需要频繁连接(JOIN)多个表,影响读取性能。因此,在一些读密集型应用(如数据仓库、报表系统)中,有时会进行"反规范化",适当增加冗余以提升查询效率。

相关推荐
l1t3 小时前
DeepSeek总结的PostgreSQL 19查询提示功能
数据库·postgresql
chenxu98b4 小时前
MySQL如何执行.sql 文件:详细教学指南
数据库·mysql
刘晨鑫14 小时前
MongoDB数据库应用
数据库·mongodb
梦想的颜色5 小时前
mongoTemplate + Java 增删改查基础介绍
数据结构·数据库·mysql
小小小米粒5 小时前
redis命令集合
数据库·redis·缓存
Irene19916 小时前
SQL 中日期的特殊性总结(格式符严格要求全大写)
sql
herinspace6 小时前
管家婆实用贴-如何分离和附加数据库
开发语言·前端·javascript·数据库·语音识别
花椒技术7 小时前
从区间锁到行锁:一次高并发写入死锁治理实战
后端·sql
步辞7 小时前
Go语言怎么用channel做信号通知_Go语言channel信号模式教程【完整】
jvm·数据库·python