术→技巧, 研发

数据库设计中的三大范式

钱魏Way · · 27 次浏览

在数据库设计中,范式是用来规范表格结构,以减少数据冗余和提高数据一致性的理论标准。第一范式(1NF)、第二范式(2NF)和第三范式(3NF)是关系型数据库设计中的关键概念,它们构成了数据库规范化的基础。

第一范式(1NF)

在数据库设计中,范式是用于指导关系型数据库设计的一系列规则或标准,目的是减少数据冗余、提高数据一致性,并确保数据的逻辑独立性。第一范式(1NF, First Normal Form)是最基础的一个范式,它要求数据库表中的每个字段都是不可分割的基本数据项,即表中的每一列都必须是原子性的,不能包含多个值。

为了满足第一范式,数据库表必须符合以下要求:

  • 原子性
    • 表中的每个字段(列)都必须是不可再分的最小数据单位。换句话说,每个字段中的数据必须是原子的,不能包含多值或重复的组。
    • 例如,如果一个字段用于存储电话号码,那么它应该只存储一个电话号码,而不是多个电话号码的列表。
  • 每个字段具有唯一的列名
    • 表中的每一列必须有一个唯一的名称,以便能够明确地引用每一个字段。
  • 行的唯一性
    • 虽然第一范式本身不要求每一行是唯一的,但通常结合其他范式(如第二范式)来确保表中没有重复的行。这通常通过定义一个主键来实现。
  • 同一列中的数据类型一致
    • 每一列中的数据都应该是相同的数据类型。这意味着如果某一列用于存储整数,那么该列中的所有数据都应该是整数。

通过遵循第一范式,可以有效地避免数据冗余和更新异常等问题。然而,需要注意的是,规范化是一个平衡的过程,过度规范化可能会导致查询复杂度增加。因此,在实际应用中,应根据具体需求权衡规范化与非规范化的利弊。

为了更好地理解 1NF 的概念,请考虑以下示例假设我们有一个表,其中包含给定公司员工的姓名、部门和办公地点,如下所示:

在此表中,Telephone Number 列是一个多值属性,这意味着它不是第一范式。删除多值属性后,规范化表将如下所示:

通过这样的重构,每个字段都变成了原子性的,每个电话号码都单独存储在自己的行中。

遵循第一范式的设计有助于确保数据的清晰性和一致性,并为进一步的规范化(如第二范式和第三范式)奠定基础。

第二范式(2NF)

第二范式(2NF, Second Normal Form)是在第一范式(1NF)的基础上进一步规范化的数据库设计原则。它的主要目标是消除由于部分依赖(Partial Dependency)导致的数据冗余问题。一个表要满足第二范式,必须首先满足第一范式,然后再满足以下条件:

  • 消除部分依赖
    • 部分依赖是指在一个复合主键(由多个字段组成的主键)中,一个非主键字段依赖于主键的一部分,而不是整个主键。在第二范式中,要求所有非主键字段必须完全依赖于整个主键,而不能仅依赖于主键的一部分。
    • 如果表中存在部分依赖,则需要对表进行分解,将依赖关系拆分到不同的表中。
  • 适用于复合主键的情况
    • 第二范式主要针对具有复合主键的表。如果一个表只有单一主键(即主键由一个字段构成),则该表自动满足第二范式,因为不存在部分依赖的可能性。

让我们用一个例子来掌握第二范式的概念。对于此示例和以下所有示例,假设一个场景:一个员工可以在多个部门工作,并且每个部门可以有多个经理。请考虑下表:

此表的主键实际上是复合键 EmployeeID, Department。非键属性是 Location,它完全取决于 Department。因此,这个表格目前不是2NF,所以为了完成归一化,我们不得不把它分成两部分。结果表将如下所示:

正如我们所看到的,我们最初的部分功能依赖关系现在被删除了,并且 Location 列完全依赖于表的主键 – Department。

通过这样的分解,所有的非主键字段都完全依赖于各自表中的主键,消除了部分依赖,从而达到了第二范式。通过遵循第二范式,数据库设计可以减少数据冗余,降低数据更新时可能引发的异常情况,提高数据的一致性和完整性。

第三范式

第三范式(3NF, Third Normal Form)是在第二范式(2NF)基础上进一步规范化的数据库设计原则。其主要目标是消除传递依赖(Transitive Dependency),以进一步减少数据冗余,提高数据一致性和完整性。要满足第三范式,一个表必须首先满足第二范式,并且还需要满足以下条件:

  • 消除传递依赖
  • 传递依赖是指在一个表中,非主键字段依赖于其他非主键字段,而这些非主键字段又依赖于主键。换句话说,如果字段A依赖于字段B,字段B依赖于主键字段C,那么就存在传递依赖。
  • 在第三范式中,要求每个非主键字段都直接依赖于主键字段,而不是通过其他非主键字段间接依赖。

让我们看看下表,了解为什么它不在 3NF 中:

在此表中,EmployeeID 确定 Department,Department 确定 Location,这意味着 EmployeeID 通过 Department 确定 Location。这表明我们有一个传递函数依赖性,它不满足 3NF。我们可以通过将这个表分成两个单独的部分来解决这个问题,就像这样:

这样,所有非 key 属性都完全依赖于 primary key。

通过遵循第三范式,可以进一步减少数据冗余,避免数据更新时可能出现的异常,确保数据的一致性和完整性。然而,正如所有的规范化过程一样,过度规范化可能导致查询变得复杂。因此,在实际应用中,设计人员需要在规范化和系统性能之间找到适当的平衡。

BCNF

BCNF(Boyce-Codd Normal Form)是数据库规范化过程中的一个高级范式,旨在解决第三范式(3NF)可能未能处理的一些特殊情况。BCNF是由R. Boyce和E.F. Codd提出的,因此得名。BCNF在确保数据一致性和消除冗余方面比第三范式更为严格。

要达到BCNF,一个关系必须首先满足第三范式,并且还需要满足以下条件:

  • 每个非平凡的函数依赖的左侧都是超键
    • 这里的“非平凡函数依赖”指的是,如果有一个函数依赖 X -> Y,那么 Y 不是 X 的子集。
    • “超键”是指一个或多个列的集合,这些列可以唯一地标识表中的一行。
    • 换句话说,BCNF要求在每一个函数依赖中,决定因素(左侧)必须是一个超键。

现在,让我们看一个例子,以便更好地理解 BCNF 的原理:

在此表中,EmployeeID 和 Department 构成主键,这意味着 Department 属性是主要属性。

此外,请注意,一个 Department 可以由多个 Manager 运行,但一个 Manager 只能运行一个 Department。这意味着 Department 和 Manager 属性之间存在依赖关系,即 department 依赖于 manager 的 ID (ManagerID -> Department)。

您可能想知道:为什么这会是一个问题?

嗯,这里的问题是 Department 是一个主要属性,而 ManagerID 不是主要属性,因此,该表不满足 BCNF。为了解决这个问题,把表放在 Boyce Codd 范式中,我们必须把表分成两个表,如下所示:

参考链接:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注