结构:
Actor <=== ActorMovie ===> Movie
ActorMovie: ActorID (fk), MovieId (fk)... ===> pk: (ActorID, MovieID)
我应该像这样为ActorMovie
表创建一个代理键吗?
ActorMovie: ActorMovieID (pk), ActorID (fk), MovieId (fk)...
答案 0 :(得分:8)
如果有用,则约定很好
“SQL Antipatterns”,第4章,“需要ID”
主键的意图
主键 - 您可以使用它来识别您的行,其中包含表中的唯一地址。这意味着,不仅某个代理列可以是主键。实际上,主键应该是:
复合与代理
有些情况下代理密钥有好处。最常见的问题 - 如果你有人名的表。 first_name
+ last_name
+ taxpayer_id
的组合可以是唯一的吗?在大多数情况下 - 是的。但从理论上讲,可能会出现重复发生的情况。因此,当代理键在任何情况下都会提供行的唯一标识时就是这种情况。
但是,如果我们谈论表之间的多对多链接,很明显,链接表将始终包含每对一次。实际上,在使用该表之前,您甚至需要检查是否存在重复项(否则 - 它是冗余行,因为除非您的设计有特殊意图存储,否则它不会包含其他信息)。因此,ActorID
+ MovieID
的组合满足主键的所有条件,并且无需来创建代理键。你可以这样做,但这没有任何意义(如果不是),因为它没有意义而不是编号行。另一方面,使用复合键,您将拥有:
作为结论 - 是的,有些情况下,代理键应该(甚至必须)应用,但在您的特定情况下,它肯定会反模式 - 使用复合键。
参考文献:
答案 1 :(得分:3)
我总是使用复合键。我的推理:
除非您有实际使用代理键的方案,否则我会使用复合键。
答案 2 :(得分:2)
我只想提一下其他海报似乎遗漏的细节:InnoDB tables are clustered。
如果你只有一个主键,你的整个表将由一个单独的B-Tree表示,这非常有效。添加代理只会创建另一个B-Tree(并且由于集群的工作方式而导致“比预期更胖”),而没有任何好处来抵消增加的开销。
Surrogates have their place,但结点表通常不是它。
答案 3 :(得分:1)
如果要将其他数据元素与连接表关联起来,例如所播放角色的名称(可能是子表),那么我当然会这样做。如果你确定你从未想过那么我认为它是可选的。
答案 4 :(得分:1)
考虑数据库设计规范化的第一个正规形式(1NF)。
我会将ActorID和MovieID作为唯一键组合,然后创建一个主键ActorMovieID。
在此处查看相同的问题:Two foreign keys instead of primary
答案 5 :(得分:1)
关于这个问题,我的观点很简单:代理主键总是可以工作,而复合键可能不会总是工作这些天中的一天,这有多种原因
因此,当你开始问自己'复合优于代理'时,你已经进入了浪费时间的过程。去代理。它总是有效。然后切换到下一步。