我有几个数据库表只包含一个列和很少的行,通常只是另一个系统中定义的内容的ID。然后使用其他表中的外键引用这些表。例如,一个表包含国家代码(SE,DK,US等)。所有值始终是唯一的自然键,它们在其他(传统)系统中用作主键。
似乎没有必要为这些表引入新的代理键,或者?
一般情况下,不应使用代理键的例外情况是什么?
答案 0 :(得分:22)
我想说必须满足以下条件:
您的自然密钥必须绝对,积极,不允许例外,独特(名称,社会安全号等等通常似乎是独特 - 但实际上并非如此)
您的自然键应该与INT一样小,例如大小不超过4个字节(不要为您的PK使用VARCHAR(50),特别是不要使用SQL Server中的群集密钥!)
你的自然键应该是稳定的,例如永远不会改变(好吧,有ISO国家代码,这几乎是给定的 - 除非像南斯拉夫或苏联这样的国家崩溃,或者像两个德国人团结一样 - 但这种情况很少见)
如果满足这些条件,您可以将自然键视为您的PK - 但这应该是所有表中的2%例外 - 而不是常态。
答案 1 :(得分:3)
我不确定当代理键不应该时会出现异常情况。我认为代理键的性质,通常是为了使引用具有全局唯一性,在应用于您描述的系统时尤为重要。
虽然您提到的每个卫星主键在其自己的范围内可能是唯一的,但您无法保证它们在互连环境的整个范围内保持唯一,尤其是在它扩展的情况下。我怀疑最初的设计师要么试图将来证明他们的系统,要么是他们学到的最新时尚;)
答案 2 :(得分:2)
自然键(在您的情况下为国家/地区代码)更好,因为
自然键的缺点是它们与信息逻辑联系在一起,如果它发生变化(有时会发生变化),你需要改变很多表,基本上是对数据库的重要部分进行了改造。
因此,如果在您的数据库中逻辑多年没有改变,请使用自然键。
答案 3 :(得分:2)
对此有一个长期的争论。如果您谷歌搜索“代理v自然键”,您将获得许多链接。所以我怀疑你会在这里得到一个辩论而不是一个明确的答案。
来自this article:
数据建模器(对于本次讨论,我包括为数据库设计表的任何人)在这个问题上划分:一些建模者发誓代理键;其他人在使用任何东西之前会死掉,而不是自然的钥匙搜索有关数据建模和数据库设计的文献不支持任何一方,除了数据仓库领域,其中代理键是维度和事实表的唯一选择。
答案 4 :(得分:0)
除了marc_s所说的,通常在链接表中不需要surrgogate键,该表是包含两个不同主键的表,用于创建多对多关系。通常,这两个字段上的复合键在这里工作正常。这是我建议使用复合键的少数几次之一,通常我更喜欢复合键上的代理键和唯一索引。
答案 5 :(得分:0)
使用自然键进行识别是一个好主意,无论何时真正可信任自然键。对于无法信任自然键的某些情况,请参阅Marc_S响应。不要过分担心效率问题。即使像VIN(车辆识别号码)这样的东西也不会拖累你的数据库。如果你认为它会做,做一些测试,意识到效率不会线性扩展。
声明主键的主要原因是防止表从第一范式滑出,从而不再表示关系。使用自动增量代理键可能会导致两行具有不同的id字段,但在其他方面相同。这将为您带来一些不是第一次正常形式的数据所带来的问题。并且用户将无法提供帮助,因为他们无法看到id字段。
如果表的行可以由两个或多个外键的某种组合确定,那么您所拥有的是关系表,有时称为链接表或联结表。通常最好声明一个由所有需要的外键组成的复合主键。
如果上述选择导致性能降低,有时可以通过创建一些额外的索引来解决。这取决于您对数据的处理方式。