数据库规范化理论是一系列用于设计关系数据库的原则和方法,目的是减少数据冗余并避免数据更新异常(如插入异常、删除异常和修改异常)。
规范化分为多个级别,通常讨论的是从第一范式(1NF)到第五范式(5NF),其中最常用的是前三范式(1NF, 2NF, 3NF)。
第一范式
第一范式要求表中的每一列都具有原子性,即不可再分。这意味着表中的每一列都应该是单一的数据项,不能是列表、集合或其他复合数据类型。此外,每一行都应该唯一标识,通常通过主键来实现。
特征
- 每一列都是不可分割的基本数据项。
- 表中不存在重复的组。
- 每一行都由一个唯一的键值来标识。
解决的问题
第一范式主要解决了数据表中的原子性问题,即表中的所有字段值都是不可分割的最小数据单位,不允许出现重复的组或数组。
第二范式
第二范式建立在第一范式的基础上,要求表中的所有非主键列完全依赖于整个主键(而不是主键的一部分),并且表必须有单一的主键。
特征
- 满足1NF。
- 所有的非主属性完全函数依赖于候选键。
- 不允许部分依赖。
解决的问题
第二范式在第一范式的基础上,解决了部分依赖的问题。即非主键属性必须完全依赖于主键,而不是仅依赖于主键的一部分。
例子
假设我们有一个关于订单的表orders
,它包含了以下信息:
订单编号 | 客户ID | 客户姓名 | 客户电话 | 商品ID | 商品数量 | 商品价格 |
---|---|---|---|---|---|---|
001 | C001 | 王五 | 12345678 | P001 | 2 | 50 |
001 | C001 | 王五 | 12345678 | P002 | 1 | 30 |
002 | C002 | 赵六 | 87654321 | P003 | 3 | 20 |
在这个表中,我们可以看到以下问题:
- 主键:假设
订单编号
和商品ID
的组合是主键。 - 部分依赖:
客户ID
、客户姓名
和客户电话
只依赖于订单编号
,而不依赖于商品ID
。
为了符合第二范式,我们需要消除部分依赖,将表拆分为多个表,每个表都有自己的主键,并且非主属性完全依赖于主键。
以下是转换后的表结构:
订单表(orders):
订单编号 | 客户ID |
---|---|
001 | C001 |
002 | C002 |
客户表(customers):
客户ID | 客户姓名 | 客户电话 |
---|---|---|
C001 | 王五 | 12345678 |
C002 | 赵六 | 87654321 |
订单详情表(order_details):
订单编号 | 商品ID | 商品数量 | 商品价格 |
---|---|---|---|
001 | P001 | 2 | 50 |
001 | P002 | 1 | 30 |
002 | P003 | 3 | 20 |
在这个新的表结构中:
- 订单表 (
orders
):只包含订单编号和客户ID,订单编号
是主键。 - 客户表 (
customers
):包含客户ID、客户姓名和客户电话,客户ID
是主键。 - 订单详情表 (
order_details
):包含订单编号、商品ID、商品数量和商品价格,订单编号
和商品ID
的组合是主键。
第三范式
第三范式建立在第二范式的基础上,要求表中的所有非主键列不仅直接依赖于主键,而且不依赖于其他非主键列。换句话说,表中的任何非主键列都不能传递依赖于主键。
特征
- 满足2NF。
- 所有的非主属性非传递依赖于候选键。
解决的问题
第三范式进一步解决了传递依赖的问题,即非主属性不仅依赖于主键,还可能依赖于其他非主属性,这样会导致数据的冗余和更新异常。
例子
假设我们有一个关于员工和部门的表employee_department
,它包含了以下信息:
员工ID | 员工姓名 | 部门ID | 部门名称 | 部门经理 |
---|---|---|---|---|
E001 | 张三 | D001 | 研发部 | 李四 |
E002 | 李四 | D001 | 研发部 | 李四 |
E003 | 王五 | D002 | 销售部 | 赵六 |
在这个表中,我们可以看到以下问题:
- 主键:假设
员工ID
是主键。 - 传递依赖:
部门ID
依赖于员工ID
(因为每个员工属于一个部门),而部门名称
和部门经理
依赖于部门ID
(因为每个部门有自己的名称和经理)。这里存在传递依赖,因为部门名称
和部门经理
是通过部门ID
间接依赖于员工ID
。
为了符合第三范式,我们需要消除传递依赖,将表拆分为多个表,每个表都有自己的主键,并且非主属性不依赖于其他非主属性。
以下是转换后的表结构:
员工表(employees):
员工ID | 员工姓名 | 部门ID |
---|---|---|
E001 | 张三 | D001 |
E002 | 李四 | D001 |
E003 | 王五 | D002 |
部门表(departments):
部门ID | 部门名称 | 部门经理 |
---|---|---|
D001 | 研发部 | 李四 |
D002 | 销售部 | 赵六 |
在这个新的表结构中:
- 员工表 (
employees
):包含员工ID、员工姓名和部门ID,员工ID
是主键。 - 部门表 (
departments
):包含部门ID、部门名称和部门经理,部门ID
是主键。
第四范式
第四范式是在第三范式的基础上进一步消除多值依赖。如果一个表已经满足3NF,但仍存在多值依赖,则需要进行进一步的分解以达到4NF。
特征
- 满足3NF。
- 没有多值依赖。
第五范式
第五范式,也称为投影-连接范式(Project-Join Normal Form),要求对于每一个非平凡的函数依赖X → Y,都有X为候选键。这可以理解为所有函数依赖都必须是平凡的或者依赖的左侧必须是一个候选键。
特征
- 满足4NF。
- 对于所有的非平凡的函数依赖X → Y,X要么是候选键,要么Y包含候选键的一部分。