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)多个表,影响读取性能。因此,在一些读密集型应用(如数据仓库、报表系统)中,有时会进行"反规范化",适当增加冗余以提升查询效率。

相关推荐
TDengine (老段)6 小时前
MNode 内部机制深度解析 — SDB、事务引擎与 DDL 处理全链路
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
这个DBA有点耶6 小时前
数据库上云 vs 自建:从成本到人力的三维对比与决策框架
数据库·经验分享·sql·创业创新·dba
shizhan_cloud6 小时前
MySQL 索引优化 + 慢查询日志
数据库·mysql
Drache_long6 小时前
MySQL数据库(故障排除)
数据库·mysql
2303_821287386 小时前
如何清洗SQL输入数据_使用框架内置的ORM处理数据交互
jvm·数据库·python
清风雅雨6 小时前
AI编程:OA流程明细表中多个金额字段由整数改为2位小数
数据库·ai编程
菜鸟上路_lbz6 小时前
sqlserver存储过程查询缓慢锁表分析
数据库·sqlserver
Elastic 中国社区官方博客6 小时前
在 Elasticsearch 中使用利润率与流行度加权来优化电商搜索
大数据·数据库·elasticsearch·搜索引擎·全文检索
van久7 小时前
Day32:项目性能优化(EF Core + 分页 + 全异步)
数据库·oracle·性能优化
Dxy12393102167 小时前
Python请求方式介绍:JSON、表单及其他常见数据传输格式
数据库·python·json