【问题标题】:Would like to Understand 6NF with an Example想通过一个例子来理解 6NF
【发布时间】:2026-02-16 04:00:01
【问题描述】:

我刚刚阅读了@PerformanceDBA 的论点:6NF 和 E-A-V。我很感兴趣。我之前对 6NF 持怀疑态度,因为它被描述为“只是”在表格上粘贴了一些时间戳列。

我一直使用数据字典,不需要被说服使用它或生成 SQL 代码。所以我希望得到一个需要用于生成代码的字典(或目录)的答案。

所以我想知道 6NF 如何处理一个非常简单的例子。物品、描述和价格表。价格随时间变化。

那么无论如何,当转换为 6NF 时,Items 表会是什么样子?什么是“爆炸表”?发生在这里?

如果该示例不适用于这么简单的表格,请随意添加必要的内容来理解这一点。

【问题讨论】:

  • 出于好奇,您所说的“我一直使用数据字典”是什么意思?在这种情况下,什么是“数据字典”?

标签: normalization


【解决方案1】:

简而言之,6NF 意味着每个关系都由一个候选键加上不超过一个其他(键或非键)属性组成。举个例子,如果一个“项目”由 ProductCode 标识,而其他属性是 Description 和 Price,那么 6NF 模式将包含两个关系(* 表示每个关系中的键):

ItemDesc {ProductCode*, Description}
ItemPrice {ProductCode*, Price}

这可能是一种非常灵活的方法,因为它可以最大限度地减少依赖关系。然而,这也是它的主要缺点,尤其是在 SQL 数据库中。 SQL 使得强制执行许多多表约束变得困难或不可能。使用上述模式,在大多数情况下,不可能强制执行每个产品必须始终具有描述和价格的业务规则。同样,您可能无法强制执行一些应该应用的复合键(因为它们的属性可能被拆分到多个表中)。

因此,在考虑 6NF 时,您必须权衡哪些依赖项和完整性规则对您很重要。在许多情况下,您可能会发现坚持 5NF 并进行规范化更实际和有用。

【讨论】:

  • " 6NF 意味着每个关系都由一个候选键加上不超过一个其他(非键)属性组成。你能给我这个定义的参考吗?
  • 结帐“关系数据库设计和实现:Jan Harrington,第 3 版,第 125 页”。(结果是无法进一步分解的表格;在大多数情况下,表格包括主键和单个非键属性。)
【解决方案2】:

我实际上开始将答案放在一起,但我遇到了麻烦,因为您(很容易理解)想要一个简单的例子。问题是多方面的。

首先,我不太了解您在关系数据库和 5NF 方面的实际专业知识水平;我没有一个起点,然后讨论 6NF 的细节,

其次,就像任何其他 NF 一样,它是杂色的。你只能勉强踏入它;您可以为某些表实现 6NF;您可以在每张桌子上全力以赴,等等。当然会有桌子爆炸,但是然后您将其标准化并消除爆炸;这是 6NF 的高级或成熟实现。当您要求最简单、最直接的示例时,提供全部或部分 6NF 级别是没有用的。

我相信您明白,有些表格可能是“5NF”,而其他表格是“6NF”。

所以我为你整理了一个。但即使这样也需要解释。

现在 SQL 几乎不支持 5NF,它根本不支持 6NF(我认为 dportas 用不同的词说同样的话)。现在,出于性能原因,我在更深层次上实现了 6NF,简化了旋转(整个表;任何和所有列,而不是 MS 中愚蠢的 PIVOT 函数),列访问等。为此,您需要一个完整的目录,这是一个扩展SQL目录,支持SQL不支持的6NF,维护数据完整性和业务规则。所以,你真的不想为了好玩而实现 6NF,只有在需要时才这样做,因为你必须实现一个目录。 (这是 EAV 人群不做的事情,这也是大多数 EAV 系统存在数据完整性问题的原因。他们中的大多数不使用 SQL 所具有的声明性引用和数据完整性。)

但是大多数实施 6NF 的人并没有实施更深层次的、完整的目录。他们有更简单的需求,因此实现了较浅的 6NF 级别。因此,让我们以此为您提供一个简单的示例。让我们从一个声明为 5NF 的普通 Product 表开始(我们不要争论 5NF 是什么)。该公司销售各种不同类型的产品,其中一半是强制性的,另一半是可选的,这意味着,根据产品类型,某些栏可能是空的。虽然他们可能在数据库方面做得很好,但 Nulls 现在是一个大问题:对于某些 ProductTypes 应该为 Not Null 的列是 Null,因为声明声明为 NULL,并且他们的应用程序代码仅与下一个人的一样好.

所以他们决定使用 6NF 来解决这个问题,因为 6NF 的副标题指出它消除了 Null 问题。第六范式是不可约范式,在此之后不会有进一步的 NF,因为数据无法进一步归一化。行已被标准化到最大程度。 6NF的定义是:

行包含主键和最多一个属性时,表处于 6NF。

请注意,根据该定义,全球数以百万计的表已经处于 6NF 中,而没有这种意图。例如。典型的参考或查找表,只有 PK 和描述。

没错。那么,我们的朋友看他们的Product表,它有8个非键属性,所以如果他们把Product表做成6NF,他们就会有8个子Product表。然后是一些列是其他表的外键的问题,这会导致更多的复杂性。他们注意到 SQL 不支持他们正在做的事情这一事实,他们必须建立一个小目录。八张表是正确的,但并不明智。他们的目的是摆脱 Null,而不是围绕每个表编写一个小子系统。

Simple 6NF Example

不熟悉关系数据库建模标准的读者可能会发现IDEF1X Notation 有助于解释示例中的符号。

因此,产品表通常会保留所有强制列,尤其是 FK,并且每个可选列、每个可空列都放置在单独的子产品表中。这是我见过的最简单的形式。五张桌子而不是八张。在 Model 中,四个子 Product 表是“in 6NF”;主产品表是“in 5NF”。

现在我们真的不需要从 Product 中选择的每个代码段都必须根据 ProductType 等确定它应该构造哪些列,所以我们提供了一个视图,它本质上提供了 5NF“视图”产品表集群。

接下来我们需要的是扩展 SQL 目录的基本原理,这样我们就可以确保各种 ProductType 的规则(数据完整性)被维护在一个地方,在数据库中,而不是依赖于应用程序代码。您可以摆脱的最简单的目录。这是从 ProductType 驱动的,因此 ProductType 现在构成了该元数据的一部分。你可以在没有目录的情况下实现这个简单的结构,但我不推荐它。

更新

需要注意的是,我在数据库中实现了所有业务规则。否则它就不是数据库(“在应用程序代码中”实现规则的概念非常有趣,尤其是现在,当我们有花店作为“开发人员”工作时)。因此,所有规则等首先实现为 SQL 声明、CHECK 约束、函数等。这保留了所有声明性引用完整性和声明性数据完整性。 SQL 目录的扩展涵盖了 SQL 没有声明的区域,然后它们被实现为 SQL。作为一个好的数据字典,它可以做的更多。例如。我不会在每次更改表或添加或更改列或其特性时都编写视图,它们是使用简单的代码生成器直接从目录+扩展创建的。

还有一个非常重要的注意事项。如果没有完成对 5NF 的完整和忠实的标准化练习,您将无法实施 6NF(或正确的 EAV)。我在每个站点看到的问题是,它们没有真正的 5NF 状态,它们有部分规范化的混搭或根本没有规范化,但他们非常重视这一点。从中创建 6NF 或 EAV 都是一场灾难。 在没有在声明性 SQL 中实现的所有业务规则的情况下从那个创建 EAV 或 6NF 是一场核灾难,燃烧多年。一分钱一分货。

结束更新。

最后,是的,至少有四个进一步的规范化级别(规范化是一个原则,不仅仅是对范式的引用),可以应用于那个简单的 6NF 产品集群,提供更多的控制,更少的表格,等等。我们走得越深,目录就越广泛。以及更高水平的性能。准备好了就问吧,我已经搭建好了模型,并在其他答案中发布了详细信息。

【讨论】:

  • @Ken。我的荣幸。当您准备好更深层次的 6NF 时,只需询问或阅读我的其他答案。如果您不知道,您可以取消勾选一个答案并勾选另一个答案。
  • “请注意,根据该定义,全球数百万张表已经处于 6NF 中,但并没有这样的意图。”好点,例如所有“全键”表都在 6NF 中。
  • @Onedaywhen。好吧,假设,上下文是它们是标准化的。而Idiot 键表示未规范化的表,它们不符合条件。
  • 哇,你为什么不警告我。我也想得到你的答案
  • @PerformanceDBA 视图表怎么没有空列,每个产品类型都有产品视图吗?
【解决方案3】:

我之前对 6NF 持怀疑态度 因为它被呈现为“仅仅” 粘贴一些时间戳列 表格。

我不太确定这种明显的误解来自何处。也许是因为 6NF 是在 Date、Darwen 和 Lorentzos 的“时间数据和关系模式”一书中引入的?无论如何,我希望这里的其他答案已经澄清了 6NF 不限于时态数据库。

我想说的一点是,尽管 6NF “在学术上受人尊敬”并且总是可以实现的,但它不一定会在每种情况下都带来最佳设计(而且不仅仅是在考虑使用 SQL 实现时)。即使是上述 6NF 的发现者和支持者似乎也同意,例如

Chris Date:“出于实际目的,坚持 5NF(和 6NF)。”

Hugh Darwen:“围绕 Date [不是人!] 的 6NF 分解将是矫枉过正......足球俱乐部的最佳设计是...... 5-and-a-bit-NF!”

Hugh Darwen:“我们在 5NF 但不是在 6NF,而且 5NF 就足够了”(几个类似的例子)。

话说回来,我也能找到相反的证据:

Chris Date: "Darwen 和我都觉得一段时间以来所有的基础 relvars 都应该是 6NF"。

实际上,我最近扩展了我们其中一款产品的 SQL 模式,以添加一个小功能。我采用了 6NF 来避免可空列,并最终得到了六个新表,我的大多数(全部?)同事会使用一个带有可空列的表(或者可能扩展现有表)。尽管我证明了几个“辅助”存储过程和一个带有INSTEAD OF 触发器的“非规范化”VIEW,但每个不得不在 SQL 级别使用此功能的编码人员都竭尽全力诅咒我 :)

【讨论】:

  • 1) 这不能回答问题 2) 这种断章取义的引用(如果不是章节,则需要阅读页面)可用于证明任何事情,包括与你试图支持什么。因此他们不能被认真对待 3) 你已经准备好迎接更多的高端同事了。
  • @PerformanceDBA: 1) 确实如此:特别是上面写着“随意添加必要的内容以表达观点”的部分。我发现最有趣的是 6NF 的主要支持者暗示“5NF 通常已经足够好”。 2)同意,阅读全文! 3)“你已经准备好迎接更多高端市场的同事了”——我很受宠若惊:) 但是在哪里可以找到......?
  • 您评论了 PerformanceDBA 的回答,即“所有“全键”表都在 6NF 中”,但事实并非如此。 6NF 意味着没有重要的 JD——即不可分解。有时 all-key 是不可分解的,有时它是。 PS 为什么 5NF 不够好?它比分解和添加 EQD 更简单。
  • @philipxy:我没有考虑过 all-key 有时是不可分解的,但现在我明白了,谢谢。附言我想我不明白为什么(或者更确切地说在什么情况下)5NF 不够好,这就是我引用其他人的原因!我真的很想听听你的回答。
【解决方案4】:

这些家伙记下了:Anchor Modeling。关于该主题的出色学术论文,并结合实际示例。他们的著作终于把我推到了考虑在即将到来的项目中使用 6nf 构建DW 的边缘。我所做的POC 工作已经证明(至少对我而言)6nf 的巨大好处不会超过成本。

【讨论】:

  • +1 用于提及该网站。我以前读过他们的东西。我不确定我是否同意他们的前提/哲学,但这是经过深思熟虑的,并且值得深思。