将数据库放入第三范式(3NF)

第三范式(3NF)是一种数据库原理,它通过建立在第一范式(1NF)和第二范式(2NF)提供的数据库规范化原则上来支持数据的完整性。

第三范式要求

数据库处于第三范式有两个基本要求:

关于主键的依赖

让我们进一步探讨所有列必须依赖主键的事实。

如果列的值可以从表中的主键和另一列导出,则它违反了3NF。 考虑带有这些列的Employees表:

LastName和FirstName都只依赖于EmployeeID的值吗? 那么,LastName可能取决于名字? 不,因为LastName中固有的东西不会建议FirstName的值。 FirstName可能取决于姓氏吗? 没有,因为同样是真的:无论LastName是什么,它都不能提供关于FirstName值的提示。 因此,该表是3NF兼容的。

但考虑一下这辆车表格:

制造商和模型可以从VehicleID派生 - 但是模型也可以从制造商派生,因为车辆模型仅由特定制造商制造。 此表设计不符合3NF标准,因此可能导致数据异常。 例如,您可能在不更新模型的情况下更新制造商,导致不准确。

为了使它符合标准,我们需要将附加依赖列移动到另一个表中,并使用外键引用它。 这将导致两个表格:

车辆表

在下表中,ModelID是Models表的外键:

模型表

这张新表格将模型映射到制造商。 如果您想要更新特定于某个模型的任何车辆信息,您可以在此表格中执行此操作,而不是在车辆表格中。

3NF模型中的派生字段

表可能包含派生字段 - 根据表中的其他列计算的字段。 例如,请考虑下面这个小部件订单表:

总数可以打破3NF合规性,因为它可以通过将单位价格乘以数量而得出,而不是完全依赖主键。 我们必须将其从桌面上移除以符合第三种正常形式。

实际上,因为它是派生的,所以最好不要将它存储在数据库中。

当执行数据库查询时,我们可以简单地计算它“实时”。 例如,我们以前可能使用此查询来检索订单号和总计:

SELECT OrderNumber,Total FROM WidgetOrders

我们现在可以使用以下查询:

SELECT OrderNumber,UnitPrice * Quantity AS总数FROM WidgetOrders

在不违反规范化规则的情况下达到相同的结果。