跳到主要内容

数据库规范化(范式)

在本节中,你将学习数据库设计中的一个重要原则——规范化(Normalization)。我们将从“为什么需要规范化”开始,一步步了解不同的“范式”到底是什么,并通过简单的例子帮助你建立直观理解。

无论你将来使用哪种数据库系统,规范化都是帮助你建立结构清晰、逻辑合理、数据一致性高的数据库模型的关键技能。

为什么要规范化?

当你设计数据库表结构时,很容易就会遇到以下问题:

  • 数据重复存储,占用空间;
  • 数据不一致,比如一个地方更新了,另一个地方没变;
  • 插入/删除/修改数据时容易出错;
  • 表结构混乱,难以维护。

为了解决这些问题,就需要对数据表进行规范化处理,也就是按照“范式”的要求,把表拆分得更合理、字段安排得更清晰。

什么是范式(Normal Form)?

你可以把“范式”理解为一种设计标准,告诉你“怎样设计表结构才更好”。在数据库设计中,最常用的是前三种范式:

范式名称简称作用
第一范式1NF消除字段中的重复数据
第二范式2NF消除字段对部分主键的依赖
第三范式3NF消除字段对非主属性的传递依赖

下面我们一一讲解。

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

定义:每个字段必须是不可再分的原子值,不能是数组、列表、集合等结构。

例如,下面是一张不符合 1NF 范式的表:

学号姓名电话
1001小明138xxx,139xxx

你看,“电话”字段里存了两个号码,这是一列多值,违反了第一范式。

正确做法(1NF):可以将“电话”单独拆成一张表。

学生表:

学号姓名
1001小明

电话表:

学号电话
1001138xxx
1001139xxx

第二范式(2NF):消除对主键的“部分依赖”

定义:在满足 1NF 的基础上,每个非主属性必须完全依赖于主键,不能只依赖主键的一部分。

适用于:主键是组合键时,要特别注意这个问题。

例如,下面是一张不符合 2NF 范式的表:

学号课程名成绩姓名
1001数学90小明
1001英语85小明

主键是(学号, 课程名),但是“姓名”只依赖于学号——这就是部分依赖

正确做法(2NF)

学生表:

学号姓名
1001小明

成绩表:

学号课程名成绩
1001数学90
1001英语85

现在,“成绩”依赖的是(学号, 课程名),“姓名”依赖的是学号,表结构就更合理了。

第三范式(3NF):消除“传递依赖”

定义:在满足 2NF 的基础上,非主属性不能依赖于另一个非主属性

换句话说,字段应该直接依赖主键,而不是间接依赖

例如,下面是一张不符合 3NF 范式的表:

学号姓名班级ID班级名
1001小明1一班

这里,“班级名”依赖的是“班级ID”,“班级ID”依赖的是“学号”——形成了传递依赖

正确做法(3NF)

学生表:

学号姓名班级ID
1001小明1

班级表:

班级ID班级名
1一班

现在,“班级名”归属于“班级”表,避免了传递依赖,结构更清晰。

小结

通过本节的学习,你应该掌握了以下关键点:

  • 规范化的目的是减少冗余、提高数据一致性;
  • 第一范式(1NF):字段必须是原子值,不能再拆;
  • 第二范式(2NF):消除对主键的部分依赖;
  • 第三范式(3NF):消除非主属性之间的传递依赖;
  • 通过分表和设置主键/外键,可以达到范式要求。

当然,实际开发中,有时为了查询效率,会对范式适当“反规范化”处理(比如合并表结构)。但前提是你先懂得如何正确规范化,才能做出合理的设计选择。