数据库第二范式(2NF)详解

数据库设计中,第二范式(2NF)是一个重要的概念,它帮助确保数据表的设计既清晰又高效。2NF的核心目的是让表专注于单一目的,这不仅有助于数据库设计的清晰性,也使得表的描述和使用更加方便,并且有助于避免修改异常。

2NF的基础是主键,它能够唯一地标识表中的每一条记录。例如,一个员工ID(EmployeeID)单独来看可能没有太多信息,但是当它与名字、身高、发色和年龄等属性结合时,就能描述出一个真实的人。

那么,什么是2NF的定义呢?

2NF - 第二范式定义

一个表处于第二范式(2NF)的条件是:

  • 表处于第一范式(1NF);
  • 表中所有非键属性完全依赖于主键。

已经了解了1NF,那么第二点要求是什么意思呢?简单来说,主键提供了一种方式来唯一地识别表中的每一条记录。当说列依赖于主键时,意味着要找到某个特定值,比如Kris的发色,首先需要知道主键,比如EmployeeID,才能查找答案。

一旦确定了表的目的,然后查看表中的每个列,并问自己:“这个列是否服务于描述主键所标识的内容?”如果答案是肯定的,那么这个列依赖于主键,并且属于这个表。如果答案是否定的,那么这个列应该移动到另一个表。

当所有列都与主键相关时,它们自然地共享一个共同的目的,比如描述一个员工。这就是为什么当一个表处于第二范式时,它具有单一目的,比如存储员工信息。

示例数据模型的问题

到目前为止,已经将示例提升到第一范式,但它存在几个问题。

第一个问题是SalesStaffInformation表有两个列并不依赖于EmployeeID。尽管它们用来描述销售人员所在的办公室,但SalesOffice和OfficeNumber列本身并不服务于描述员工是谁。

第二个问题是,Customer表中有几个属性并不完全依赖于整个Customer表的主键。对于一个给定的客户,不应该需要知道CustomerID和EmployeeID才能找到客户。理论上,只需要知道CustomerID。因此,Customer表没有处于2NF,因为有些列并不依赖于完整的主键。它们应该被移动到另一个表。

这些问题在下面的红色标记中被识别出来。

由于红色标记的列并不完全依赖于表的主键,因此它们应该属于其他地方。在这两种情况下,列被移动到新的表中。

对于SalesOffice和OfficeNumber,创建了一个SalesOffice。然后在SalesStaffInformation中添加了一个外键,以便仍然可以描述销售人员所在的办公室。

要使Customer成为第二范式表的更改有点棘手。与其将违规列CustomerName、CustomerCity和CustomerPostalCode移动到新表,不如认识到问题在于EmployeeID!这三个列并不依赖于这个键的部分。实际上,这个表试图服务于两个目的:

  • 指示每个员工联系的客户;
  • 识别客户及其位置。

暂时从表中移除EmployeeID。现在表的目的很清楚了,它是用来识别和描述每个客户的。

现在让创建一个名为SalesStaffCustomer的表,用来描述销售人员联系的客户。这个表有两个列,CustomerID和EmployeeID。它们一起形成一个主键。单独来看,它们是Customer和SalesStaffInformation表的外键。

通过这些更改,数据模型处于第二范式,如下图所示:

为了更好地可视化,这里是带有数据的表。

当查看表中的数据时,注意大部分冗余已经被消除。同时,看看是否能发现任何更新、插入或删除异常。这些异常也消失了。现在可以删除所有销售人员,但保留客户记录。此外,如果所有SalesOffices关闭,并不意味着必须删除包含销售人员的记录。

SalesStaffCustomer表是一个奇怪的表。它只是所有的键!这种类型的表被称为交叉表。交叉表在需要建模多对多关系时非常有用。

每个列都是一个外键。如果查看数据模型,会注意到SalesStaffInformation表和Customer表都有一个到这个表的多对一关系。实际上,这个表允许将两个表连接在一起。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485