数据库三范式:数据规范的核心准则

124 阅读4分钟

数据库三范式:减少数据冗余与确保一致性

这个问题是数据库设计的基础,理解三范式能从根源避免数据冗余和不一致!数据库三范式的核心是逐步减少数据冗余、规范数据存储,每一级范式都建立在对上一级的满足之上。

image.png

核心定义

  • 第一范式(1NF):列不可再分,确保数据原子性。

  • 第二范式(2NF):在1NF基础上,消除部分函数依赖,所有非主键列完全依赖于主键。

  • 第三范式(3NF):在2NF基础上,消除传递函数依赖,非主键列不依赖于其他非主键列。


第一范式(1NF):列不可再分

案例:反例(不满足1NF)

假设设计“用户表”,其中“联系方式”列包含电话和邮箱,格式如下:

用户ID(主键)用户名联系方式
1张三138xxxx1234,zhangsan@xxx.com
2李四139xxxx5678,lisi@xxx.com
问题

“联系方式”列可拆分为“电话”和“邮箱”两个独立字段,不符合“原子性”要求,后续查询、筛选(如按电话搜索)会非常不便。

正例(满足1NF)

拆分可分割列,确保每列只存储单一类型数据:

用户ID(主键)用户名电话邮箱
1张三138xxxx1234zhangsan@xxx.com
2李四139xxxx5678lisi@xxx.com

第二范式(2NF):消除部分函数依赖

前提
  • 满足1NF。

  • 主键必须是“复合主键”(由多个字段组成),才可能存在“部分依赖”(非主键列只依赖复合主键中的某一个字段)。

案例:反例(不满足2NF)

假设设计“订单详情表”,复合主键为“订单ID+商品ID”,表结构如下:

订单ID(主键1)商品ID(主键2)商品名称商品单价购买数量订单金额
001A01手机5000210000
001A02耳机3001300
002A01手机500015000
问题
  • “商品名称”“商品单价”只依赖“商品ID”(复合主键中的一个字段),不依赖“订单ID”,属于“部分函数依赖”。

  • 数据冗余严重:同一商品(如A01手机)的名称和单价重复存储,修改时需同步修改所有相关记录,易出现不一致。

正例(满足2NF)

拆分表,消除部分依赖,拆分为“订单详情表”和“商品表”:

  1. 商品表(主键:商品ID)
商品ID商品名称商品单价
A01手机5000
A02耳机300
  1. 订单详情表(主键:订单ID+商品ID)
订单ID商品ID购买数量订单金额
001A01210000
001A021300
002A0115000

第三范式(3NF):消除传递函数依赖

前提
  • 满足2NF。

  • 非主键列之间存在“传递依赖”(A依赖主键,B依赖A,即B传递依赖主键)。

案例:反例(不满足3NF)

基于2NF的“订单详情表”,扩展后包含“用户地址”,表结构如下:

订单ID(主键)用户ID商品ID购买数量订单金额用户地址
001U01A01210000北京市朝阳区
002U01A021300北京市朝阳区
003U02A0115000上海市浦东新区
问题
  • 主键是“订单ID”,“用户地址”依赖“用户ID”,而“用户ID”依赖“订单ID”,属于“传递依赖”(用户地址→用户ID→订单ID)。

  • 数据冗余:同一用户(如U01)的地址重复存储,用户修改地址时需同步修改所有相关订单记录,易出错。

正例(满足3NF)

拆分表,消除传递依赖,拆分为“订单表”“用户表”“商品表”(已存在):

  1. 用户表(主键:用户ID)
用户ID用户地址
U01北京市朝阳区
U02上海市浦东新区
  1. 订单表(主键:订单ID)
订单ID用户ID商品ID购买数量订单金额
001U01A01210000
002U01A021300
003U02A0115000

关键补充

  • 三范式的核心是“减少冗余、保证数据一致性”,但并非绝对:实际设计中可能为了查询效率,适当保留少量冗余(如数据仓库中的汇总表),这是“反范式”设计,需结合场景权衡