跳转到内容

数据库设计范式详解

范式是数据库设计的规则,目的是让数据结构更合理,避免以下问题:

  • 数据冗余(同一份数据重复存储)
  • 更新异常(修改数据时可能遗漏某些地方)
  • 插入/删除异常(操作数据时可能破坏完整性)

范式的划分是逐层递进的,每个范式都建立在满足前一个范式的基础上。


含义:是最基本的范式,它要求数据库表的每一列都是不可分割的原子数据项,不能是列表、数组等多值数据。 目标:消除重复字段,确保每列不可再分。
示例
×:学生表中有一个字段 课程 存储 [“数学”,“英语”](多值)。
:拆分为两行,每行存储一门课程:

学生ID课程
1001数学
1001英语

含义:在满足1NF的基础上,消除部分依赖(非主属性必须完全依赖主键)。
目标:解决“一个表有多个主键”导致的冗余问题。
示例
×:订单表(订单ID和产品ID联合主键)中直接存储产品名称:

订单ID产品ID产品名称
1001P001手机
1002P001手机

PS:产品名称在订单表中是冗余的,因为订单表中已经存储了产品ID,通过产品ID可以直接查询到产品名称。

:拆分为两张表:

订单表(主键:订单ID):

订单ID产品ID
1001P001
1002P001

产品表(主键:产品ID):

产品ID产品名称
P001手机

含义:在满足2NF的基础上,消除传递依赖(非主属性不能依赖其他非主属性)。
目标:解决“通过非主属性间接依赖主键”导致的冗余问题。
示例
×:学生表中存储所属学院和学院电话:

学生ID姓名所属学院学院电话
1001张三信息学院010-12345678

PS:学院电话依赖所属学院,而所属学院依赖学生ID(传递依赖)。
:拆分为两张表:

学生表(主键:学生ID):

学生ID姓名所属学院
1001张三信息学院

学院表(主键:学院名称):

学院名称学院电话
信息学院010-12345678

含义:在满足3NF的基础上,消除多值依赖(存在多个属性间接依赖同一张表)。
目标:解决“多对多关系直接存储”导致的冗余问题。
示例
×:学生课程表中直接存储学生ID和课程ID的多对多关系:

学生ID课程ID课程名称教师
1001C001数学A老师
1001C002英语B老师
1002C001数学A老师
1002C002英语B老师

PS:学生课程表中存在多值依赖,即学生ID和课程ID直接存储在同一张表中。
:拆分为两张表:

学生课程表(主键:学生ID和课程ID):

学生ID课程ID
1001C002
1002C001
1002C002
1001C001

课程表(主键:课程ID):

课程ID课程名称教师
C001数学A老师
C002英语B老师

含义:BCNF是3NF的加强版,要求所有非主属性的依赖关系中,决定因素必须是超级码(即决定因素包含主键)
目标:解决3NF未覆盖的“主属性依赖主属性”问题。
示例
×:反例:项目表(主键:项目ID)中存储负责人和部门:

项目ID负责人部门
P001张三技术部
P003王五财务部

PS:项目表中存在主属性依赖主属性,即项目ID决定了负责人和部门,因此不满足BCNF。

:满足BCNF:

项目表(主键:项目ID):

项目ID负责人
P001张三
P003王五

项目负责人表(主键:负责人):

负责人部门
张三技术部
王五财务部

1. 第一步:满足1NF
确保每个字段不可再分(原子性)。
2.第二步:满足2NF
检查是否存在“部分依赖”(非主属性依赖主键的一部分),若有则拆分表。
3.第三步:满足3NF
检查是否存在“传递依赖”(非主属性依赖其他非主属性),若有则拆分表。
4.第四步:满足BCNF
检查是否存在“主属性依赖主属性且不满足超级码”,若有则拆分表。
5.第五步:满足4NF
检查是否存在“多对多关系导致的冗余”,若有则通过中间表拆分。


范式级别核心问题解决方案示例场景
1NF字段可再分拆分字段为原子性存储多值字段(如数组)
2NF部分依赖将依赖部分拆分到新表联合主键表(如订单表)
3NF传递依赖将被依赖字段拆分到新表学生表存储学院信息
BC范式主属性非超级码决定拆分为独立表项目表存储部门负责人
4NF多值依赖通过中间表分解多对多关系学生选课关系

1NF:字段不可分,原子性第一。
2NF:主键要完整,部分依赖拆。
3NF:非主不传传,依赖要直接。
BCNF:决定因素是超码,主属性不乱依赖。
4NF:多对多拆中间,避免冗余存。