Database design 使用复合键?还是始终使用代理密钥?

Database design 使用复合键?还是始终使用代理密钥?,database-design,primary-key,Database Design,Primary Key,重复: 如果我有这些表(*=主键): 这样更好吗 user_group user_id* group_id* user_group id* user_id group_id 还是这样更好 user_group user_id* group_id* user_group id* user_id group_id 我总是选择尽可能窄的、静态的(从不更改)键,因此我通常倾向于使用代理INT作为键,而不是复合键 如果您想引用另一个表中的复合键,那么您必须始

重复:

如果我有这些表(*=主键):

这样更好吗

user_group
  user_id*
  group_id*
user_group
  id*
  user_id
  group_id
还是这样更好

user_group
  user_id*
  group_id*
user_group
  id*
  user_id
  group_id

我总是选择尽可能窄的、静态的(从不更改)键,因此我通常倾向于使用代理INT作为键,而不是复合键

如果您想引用另一个表中的复合键,那么您必须始终指定几个条件——这有时会变得非常笨拙

还可以查看其中的一些链接:

(当然,其他人可能会发布至少10个亲自然键链接:-))

使用代理密钥没有什么害处—去吧!:-)


Marc

给定的用户id和组id都已经是代理密钥,因此保证是唯一的(给定应用程序的正确实现),添加第三个id是完全多余的


除非您正在使用某种ORM(不幸的是),它通常会使复合键的处理更加复杂。在这种情况下,您必须评估冗余成本与所选ORM的易开发性。

每当我从联接表中省略代理主键时,我都会后悔。当我开始编写代码来管理关系时,似乎有一个代理主键非常方便。我通常遵循活动记录模式,并且使用ASP.NET MVC,因此您的里程数可能会有所不同。在MVC的世界里,有一个可以放在URL末尾的id键是非常有利的。

我通常同意Vinko的观点,但是如果你使用ORM,比如Hibernate,如果你给所有东西一个代理键,那么(你和Hibernate之间)关系会更愉快。

我通常推荐“人工键”(你称之为“代理”),因为它们在DB之外基本上没有意义,你可以保证它们永远不会因为外部环境而改变(而关于实体的各种其他数据也可能会改变)


但是您的
user\u组
表是典型的“两个外键,仅此而已”用于实现多:多关系的安排是另一种情况——所讨论的两个外键与代理项一样受您的控制。非实体的代理项键,即仅代表一小部分关系的行,基本上只是死重,我建议您将其删除。

T第一个例子就足够了。即使您要向多对多表构造添加属性(如
is\u main\u grp
等),链接表中也不需要真正的代理,而且您可能总是希望对
用户id
组id
有唯一的约束

仅当您要在链接关系上挂起另一个多对一关系(如标签),然后我会考虑在
用户组
表中设置一个代理,直到需要时我才会这样做(因为代理相对容易添加):


更好的是主观的。两者都很好。我的个人投票支持复合键,但还是个人偏好。这是其他几个问题的重复。这是一个合法的问题,但之前已经被问过并回答过。显示为重复的链接有一个可接受的答案,但实际上并没有回答这个问题uestion.但链接是数据库设计工件,与对象模型无关-它只是允许数据库链接实体-此表甚至不应该对应用程序可见。@CadeRoux严格来说不是真的。链接表经常存在,因为应用程序需要它们作为业务逻辑的一部分。许多应用程序将更新链接表以维护模型内的特定关系。这已经有很长一段时间了,但这里的要点是,链接表中的任何代理项都可能不需要公开。如果您的API是“停止将此对象链接到另一个对象”,则接口中需要这两个对象ID,而不是链接行的代理键。我认为问题在于,由于数据库成员身份实现而产生的链接“对象”是否被提升到与常规对象模型对象相同的级别。最终,这是一个关于设计的哲学问题。替代API是“按链接id删除此链接"它公开了实现。为什么?以什么方式添加一个id比添加两个id好得多?基本原因是在MVC中,url模式通常是/controller/action/id。如果我不使用代理键,那么我的url最终会是/controller/action/?user\u id=…&group\u id=…,这也意味着我需要在查看为隐藏的输入等。单个id正好更适合该模式。为什么会有指向链接“对象”的URL?只有指向组实体或成员实体的URL。链接不应是解决方案空间中的对象。链接是数据库设计的产物,有助于解决方案空间中的对象集合成员身份。例如,当您要删除关联时。或当联接表实际具有(或获取)时更多信息——假设它代表一个事件的注册,最终会得到一个相关的费用和时间戳。根据我的经验,有足够多的时间我没有使用代理密钥,后来我不得不添加代理密钥,现在我总是使用它。在这个例子中,UserId和GroupId不是自然密钥。它们是外来的在这种情况下,甚至不会出现自然密钥的问题。但如果需要更新,例如更改特定用户的组id,则很难更新复合密钥。不是吗?