想象一下,您在处理一个庞大且无结构的数据库,里面充斥着重复、冗余的信息。每一次更新或删除操作都可能酿成灾难,带来错误与不一致。第三范式(3NF)是一种行之有效的数据库规范化方法,可以避免这种混乱。实施 3NF 能清理您的数据结构,确保其高效、有序,并且没有不必要的冗余。
本文将探讨 3NF 的工作原理、价值所在以及如何落地实施。我们还会将 3NF 与其他范式进行对比,了解各自的适用场景。任何人学习这些结构都会受益,但如果您是数据库设计师或数据科学家,这方面的知识尤其重要,因为它能显著简化您的工作并让数据库更可靠。如果您对整体的数据库设计感兴趣,不妨看看我们的完整数据库设计课程。
第三范式(3NF)定义
第三范式是数据库规范化中的关键概念,旨在移除不必要的依赖。3NF 建立在第一范式(1NF)和第二范式(2NF)之上,也就意味着它继承了它们的规则:1NF 要求每个单元格的值是原子的(不可再分),2NF 要求消除对复合主键的部分依赖。在此基础上,3NF 进一步消除传递依赖,即非键属性通过其他非键属性间接依赖主键的情况。
通过聚焦这一点,3NF 确保表中的每个非键列都只直接依赖于主键,而不依赖其他任何因素。从更实际的角度看,3NF 有助于在插入、更新或删除数据时尽量减少冗余并避免异常。
20 世纪 70 年代,Edgar F. Codd 提出了 3NF,用以形式化实现完全规范化的数据库结构所需的条件。几年后,Carlo Zaniolo 对其进行了重新表述,更清晰地阐明了“经典”3NF 与更严格的 Boyce-Codd 范式(BCNF)之间的差异。先别着急关注 BCNF,我们将在后文再谈。
理解第三范式的条件
那么,实现 3NF 究竟需要满足哪些条件?一张表要符合 3NF,需要满足以下几点:
- 满足 2NF:这意味着数据已是原子的,没有重复分组,也不存在对任何复合键的部分依赖。

3NF 包含 2NF 和 1NF。图:作者自制
- 无传递依赖:这是关键规则。在 3NF 的表中,任何非主键列都必须只依赖于主键,而不能通过其他非键列间接依赖。
下面我们来看这在实践中意味着什么。
分解表以实现 3NF
我们一起来走一遍将表分解至 3NF 的过程。文中将使用一些来自 DataCamp 课程的示例数据展示每一步。
步骤 1:识别传递依赖
首先,我们要寻找表中是否存在对主键的间接依赖。经验法则是:如果某个属性依赖的不是主键本身,那就意味着存在传递依赖。这表明可能需要对表进行拆分。
看看下面三张表。哪一张存在传递依赖?
表 1:Course(课程)
表 2:Instructor(讲师)
| Instructor ID | Instructor Name | Expertise |
|---|
| 1 | Sarah Johnson | Data Science |
| 2 | Tom Williams | Machine Learning |
| 3 | Emily Brown | Python |
表 3:Enrollments(选课)
答案是……表 3!
在这张表中,Course Name 依赖于 Course ID,但并不直接依赖于Enrollment ID(主键)。这种间接依赖使得Course Name 成为传递依赖。
步骤 2:将数据拆分到新表
为了解决传递依赖,我们将把表 1 拆成两张表。每张表只关注直接依赖的数据。
修订后的选课表
| Enrollment ID | Student Name | Course ID |
|---|
| 1001 | Alice Smith | 201 |
| 1002 | Bob Green | 202 |
| 1003 | Charlie Blue | 201 |
课程表
现在,每张表只包含直接依赖其主键的信息:Course ID 现在是Course Name 在Courses 表中的主键,而Enrollment ID 是Enrollments 表中的主键。
通过这种分解,这些表现已满足 3NF 要求,消除了冗余,确保每张表只存储直接相关的信息。
如果您想亲手创建自己的数据库,可以看看我们的创建 PostgreSQL 数据库课程。如果您已有一定基础,可以尝试Snowflake 数据建模入门,其中涵盖实体-关系和维度建模等理念。
使用第三范式的优缺点
那么,为什么要费这么大劲去达到 3NF?主要优势如下:
- 提升数据完整性:通过消除传递依赖,3NF 有助于确保更新和删除不会导致跨表数据冲突或过时。
- 减少冗余:冗余更少意味着数据库更易维护,存储占用也更低。
- 简化数据维护:将相似信息放入专门的表中,可以更轻松地更新记录,而不用追踪重复项。
话虽如此,虽然 3NF 支持数据准确性,但也可能导致数据更为分散,从而因额外的表连接让复杂查询变慢。在需要速度优先于规范化的场景中,BCNF 或 4NF 可能更为实际。
对比:第一、第二、第三范式与 BC 范式
让我们看看不同范式之间的差异。
对比表:第一、第二与第三范式
下面这张对比表有助于您理解 1NF、2NF 和 3NF 的要求。
| Feature | 1NF | 2NF | 3NF |
|---|
| Atomic data | ✅ | ✅ | ✅ |
| No partial dependencies | ❌ | ✅ | ✅ |
| No transitive dependencies | ❌ | ❌ | ✅ |
BCNF 是 3NF 的“更严格”形式,可进一步消除因候选键重叠而产生的异常。它在复杂场景中尤其有用,当 3NF 仍未完全消除依赖时适用。BCNF 适用于这样的情况:某个非主属性依赖于复合候选键的一部分。听起来有点复杂,我们用一个例子来拆解。
当前结构(符合 3NF)
在为实现 3NF 而进行分解后,我们得到了如下两张表:
选课表
| Enrollment ID | Student Name | Course ID |
|---|
| 1001 | Alice Smith | 201 |
| 1002 | Bob Green | 202 |
| 1003 | Charlie Blue | 201 |
课程表
在这个结构中,每张表都处于 3NF,不存在传递依赖,数据已适当规范化。
引入新需求
现在,让我们在课程表(Courses)中加入一个新属性:Classroom(上课教室)。这个新属性可能会引发需要 BCNF 的场景。
更新后的课程表(3NF)
在这里,Course ID 仍是主键,其他属性都直接依赖于它。但我们假设有一条新规则:每间教室同一时间只能容纳一个科目。同时假设Course Name “SQL Fundamentals” 可在不同的Course ID(如 201、204 等)下开设,只要上课时间不同。在这种情况下,每次“SQL Fundamentals”的开课仍都在 “Room 101”,而不取决于具体的Course ID。因此,Course Name 也能唯一决定Classroom。
这意味着我们现在有两个候选键:
- Course ID
- Course Name
在这两个候选键并存的情况下,出现了 3NF 未覆盖的问题:Classroom 依赖于Course Name,而不仅仅是Course ID。
应用 BCNF
为消除这一依赖问题,我们需要进一步将Courses 表分解为两张更符合 BCNF 的表:
- 新的Courses 表,仅包含Course ID 和Course Name。
- 新增CourseDetails 表,存储Course Name 与Classroom 的对应关系。
如下所示:
修订后的课程表(BCNF)
CourseDetails 表(BCNF)
采用这一新结构后,每张表都满足 BCNF 的条件:
- 在Courses 表中,Course ID 是主键,所有属性仅依赖于它。
- 在CourseDetails 表中,Course Name 是主键,而Classroom 只依赖于Course Name。
这种设置消除了由候选键重叠引起的任何依赖问题,确保结构严格规范化。
结论
第三范式是数据库设计人员保持数据干净、一致、远离问题依赖的有力工具。借助 3NF,数据完整性得到增强,管理更顺畅,冗余更少。请记住,3NF 在大多数情况下都非常有效,但对于更复杂的数据库,诸如 BCNF 或 4NF 等更高范式可能会更合适。
如果这篇文章对您有所帮助,欢迎更进一步,获取我们的SQL 助理认证。这是验证您的 SQL 与数据库管理技能、并向潜在雇主展示您专业能力的绝佳方式!
想象一下,您在处理一个庞大且无结构的数据库,里面充斥着重复、冗余的信息。每一次更新或删除操作都可能酿成灾难,带来错误与不一致。第三范式(3NF)是一种行之有效的数据库规范化方法,可以避免这种混乱。实施 3NF 能清理您的数据结构,确保其高效、有序,并且没有不必要的冗余。
本文将探讨 3NF 的工作原理、价值所在以及如何落地实施。我们还会将 3NF 与其他范式进行对比,了解各自的适用场景。任何人学习这些结构都会受益,但如果您是数据库设计师或数据科学家,这方面的知识尤其重要,因为它能显著简化您的工作并让数据库更可靠。如果您对整体的数据库设计感兴趣,不妨看看我们的完整数据库设计课程。
第三范式(3NF)定义
第三范式是数据库规范化中的关键概念,旨在移除不必要的依赖。3NF 建立在第一范式(1NF)和第二范式(2NF)之上,也就意味着它继承了它们的规则:1NF 要求每个单元格的值是原子的(不可再分),2NF 要求消除对复合主键的部分依赖。在此基础上,3NF 进一步消除传递依赖,即非键属性通过其他非键属性间接依赖主键的情况。
通过聚焦这一点,3NF 确保表中的每个非键列都只直接依赖于主键,而不依赖其他任何因素。从更实际的角度看,3NF 有助于在插入、更新或删除数据时尽量减少冗余并避免异常。
20 世纪 70 年代,Edgar F. Codd 提出了 3NF,用以形式化实现完全规范化的数据库结构所需的条件。几年后,Carlo Zaniolo 对其进行了重新表述,更清晰地阐明了“经典”3NF 与更严格的 Boyce-Codd 范式(BCNF)之间的差异。先别着急关注 BCNF,我们将在后文再谈。
理解第三范式的条件
那么,实现 3NF 究竟需要满足哪些条件?一张表要符合 3NF,需要满足以下几点:
3NF 包含 2NF 和 1NF。图:作者自制
下面我们来看这在实践中意味着什么。
分解表以实现 3NF
我们一起来走一遍将表分解至 3NF 的过程。文中将使用一些来自 DataCamp 课程的示例数据展示每一步。
步骤 1:识别传递依赖
首先,我们要寻找表中是否存在对主键的间接依赖。经验法则是:如果某个属性依赖的不是主键本身,那就意味着存在传递依赖。这表明可能需要对表进行拆分。
看看下面三张表。哪一张存在传递依赖?
表 1:Course(课程)
表 2:Instructor(讲师)
表 3:Enrollments(选课)
答案是……表 3!
在这张表中,Course Name 依赖于 Course ID,但并不直接依赖于Enrollment ID(主键)。这种间接依赖使得Course Name 成为传递依赖。
步骤 2:将数据拆分到新表
为了解决传递依赖,我们将把表 1 拆成两张表。每张表只关注直接依赖的数据。
修订后的选课表
课程表
现在,每张表只包含直接依赖其主键的信息:Course ID 现在是Course Name 在Courses 表中的主键,而Enrollment ID 是Enrollments 表中的主键。
通过这种分解,这些表现已满足 3NF 要求,消除了冗余,确保每张表只存储直接相关的信息。
如果您想亲手创建自己的数据库,可以看看我们的创建 PostgreSQL 数据库课程。如果您已有一定基础,可以尝试Snowflake 数据建模入门,其中涵盖实体-关系和维度建模等理念。
使用第三范式的优缺点
那么,为什么要费这么大劲去达到 3NF?主要优势如下:
话虽如此,虽然 3NF 支持数据准确性,但也可能导致数据更为分散,从而因额外的表连接让复杂查询变慢。在需要速度优先于规范化的场景中,BCNF 或 4NF 可能更为实际。
对比:第一、第二、第三范式与 BC 范式
让我们看看不同范式之间的差异。
对比表:第一、第二与第三范式
下面这张对比表有助于您理解 1NF、2NF 和 3NF 的要求。
BCNF 是 3NF 的“更严格”形式,可进一步消除因候选键重叠而产生的异常。它在复杂场景中尤其有用,当 3NF 仍未完全消除依赖时适用。BCNF 适用于这样的情况:某个非主属性依赖于复合候选键的一部分。听起来有点复杂,我们用一个例子来拆解。
当前结构(符合 3NF)
在为实现 3NF 而进行分解后,我们得到了如下两张表:
选课表
课程表
在这个结构中,每张表都处于 3NF,不存在传递依赖,数据已适当规范化。
引入新需求
现在,让我们在课程表(Courses)中加入一个新属性:Classroom(上课教室)。这个新属性可能会引发需要 BCNF 的场景。
更新后的课程表(3NF)
在这里,Course ID 仍是主键,其他属性都直接依赖于它。但我们假设有一条新规则:每间教室同一时间只能容纳一个科目。同时假设Course Name “SQL Fundamentals” 可在不同的Course ID(如 201、204 等)下开设,只要上课时间不同。在这种情况下,每次“SQL Fundamentals”的开课仍都在 “Room 101”,而不取决于具体的Course ID。因此,Course Name 也能唯一决定Classroom。
这意味着我们现在有两个候选键:
在这两个候选键并存的情况下,出现了 3NF 未覆盖的问题:Classroom 依赖于Course Name,而不仅仅是Course ID。
应用 BCNF
为消除这一依赖问题,我们需要进一步将Courses 表分解为两张更符合 BCNF 的表:
如下所示:
修订后的课程表(BCNF)
CourseDetails 表(BCNF)
这种设置消除了由候选键重叠引起的任何依赖问题,确保结构严格规范化。
结论
第三范式是数据库设计人员保持数据干净、一致、远离问题依赖的有力工具。借助 3NF,数据完整性得到增强,管理更顺畅,冗余更少。请记住,3NF 在大多数情况下都非常有效,但对于更复杂的数据库,诸如 BCNF 或 4NF 等更高范式可能会更合适。
如果这篇文章对您有所帮助,欢迎更进一步,获取我们的SQL 助理认证。这是验证您的 SQL 与数据库管理技能、并向潜在雇主展示您专业能力的绝佳方式!