假设我在数据库上有两个表 T 10和 T 11,分别有 10 和 11 列,其中 10 列在两者上完全相同。
我违反了什么(如果有)规范化规则?
假设我在数据库上有两个表 T 10和 T 11,分别有 10 和 11 列,其中 10 列在两者上完全相同。
我违反了什么(如果有)规范化规则?
编辑:我被告知理论上没有违反范式。由于这是公认的答案,因此我将其留在这里以供参考,并且因为考虑 3NF 在实践中可能有助于避免问题中的此类情况。
您违反了第三范式 (3NF),因为如果两个表中保存的数据几乎相同,那么每个表的每个属性都不会直接依赖于其各自表的键。
信不信由你,跨表复制列本身并没有违反理论范式。除了域/键范式 (DKNF) 之外,范式是根据单个而不是多个表定义的。DKNF 是根据约束来定义的,一般情况下没有约束。因此,如果违反正常形式:
考虑范式,使用维基百科文章中的简短定义:
该表忠实地表示一个关系,并且没有重复组。
这个相当直截了当。“重复组”一词在理论上有多种含义,但它们都与重复的列或数据无关。
表中没有非主属性在功能上依赖于任何候选键的适当子集。
在这里,要检查的重要术语是“功能依赖性”。本质上,函数依赖是您将关系投影到两列 X 和 Y,并以函数 X → Y 结束。两个(或更多)表之间不能有函数依赖*。此外,候选键不能跨越多个表。
每个非主属性都非传递地依赖于表中的每个候选键。
传递依赖是根据函数依赖定义的:传递依赖是一种依赖,其中 X → Z 仅因为 X → Y 和 Y → Z。X、Y 和 Z 必须在同一个表中,因为它们是函数依赖。
表中的每个非平凡多值依赖项都是对超键的依赖项。
多值依赖有点棘手,但可以用一个例子来说明:“只要元组 (a,b,c) 和 (a,d,e) 存在于 r 中,元组 (a,b,e) 和 ( a,d,c) 也应该存在于 r" 中(其中 "r" 是一个表)。最重要的是,对于手头的问题,多值依赖仅适用于单个表。
表中的每个重要连接依赖项都隐含在表的超键中。
如果一个表可以表示为其他表的自然连接,则它具有连接依赖关系。但是,这些其他表不需要存在于数据库中。如果示例中的表 T 11具有连接依赖关系,即使您删除了表 T 10 ,它仍然会有一个
表完全没有非平凡的连接依赖关系(参考广义连接运算符)。
5NF 的推理相同。
表中的每个非平凡函数依赖要么是基本键属性的依赖,要么是对超键的依赖。
2NF 的推理相同。
表中的每一个重要的函数依赖都是对超键的依赖。
2NF 的推理相同。
表上的每个约束都是表的域约束和键约束的逻辑结果。
如果 T 11有一个依赖于 T 10的约束,那么它要么是一个关键约束,要么是一个仍然引用 T 10的更复杂的约束。后一种情况不是问题中提到的一般情况。换句话说,虽然可能存在具有违反 DKNF 的重复列的特定模式,但通常情况并非如此。此外,是根据多个表定义的约束(不是正常形式)和导致 DKNF 违规的约束(不是列重复)。
标准化的目的包括防止异常。但是,规范化并不完整,因为它不能保证关系数据库完全没有异常。这是实践偏离理论的一个例子。
如果这仍然不能说服您,请考虑架构 KM. 的注释提示,其中 T 11表示 T 10的历史(或版本)版本。T 11的主键由与 T 10相同的主键列以及额外的列(日期/版本列)组成。T 11具有不同的候选键,这使得易发生异常和无异常的标准化设计之间存在差异。
*有人可能认为您可以使用连接来创建两个表之间的依赖关系。虽然连接可能会创建一个具有依赖关系的表,但依赖关系存在于该表上,而不是连接的组成部分之间。在目前的情况下,这再次意味着其中一个表将是一个连接表,并且会受到依赖关系本身的影响,而与数据库中的另一个表无关。
也许是避免冗余数据的规则?(即两个表中的相同数据)
如果 11 列中有 10 列是相同的,为什么这不能只是一个表,其中第 11 列留空(以及可能的第 12 列来表示它是哪种类型的数据,即它本来应该是哪个表在最初)?
这取决于表中的内容。
如果没有记录相互关联(例如,如果一个表只是源自第一个表但从第一个表中删除的存档记录),则您没有违反任何规则。
但是,如果每个表中的记录相同,则存在依赖性问题——第十一列仅依赖于记录中的键值,而不依赖于其他列。假设主键中不涉及所有十列,则您违反了第三个 NF。
拥有两个相同或接近相同的关系本身并不违反任何通常的范式。Outis 已经非常全面地解释了原因。然而,这很可能违反了正交设计原则,这是关系数据库设计理论的另一个方面。
如果所有 10 列都是您的键的一部分,那么第二范式:消除冗余数据。具体来说,这属于“非代理与代理主键”的困境——老实说,我不记得这两个选择中的任何一个是“违反”2NF,但代理键肯定更接近 2NF 的精神
只有主键在表之间可能是冗余的。在多个表中包含任意数量的非主键列违反了第三范式。