我已经看到我们可以使用复合键,其中主键由两个表的组合主键组成。
喜欢人和书籍
person_id and book_id will make the primary key.
但我想问一下,我们需要硬编码编程langauge
我的意思是,我可以使用任何名称的单独列作为主键 然后我不必硬编码它,我可以正常执行我的功能,如
id,person_id ,book_id
答案 0 :(得分:8)
永远不应在“新”应用程序中考虑复合键。过去曾经使用它们的人曾经认为“商业钥匙”比“代理钥匙”更好。
编辑:正如克里斯所说,我正在扩大我的答案。
首先让我说明我将这个问题理解为“复合主键”与“代理键”。
此外,我承认存在一个用例,其中复合键是有意义的:在交叉引用表中,也称为“链接表”。它们用于多对多表中,并且只包含两个字段,两个字段都是形成外部参照表主键的外键。例如,UserRole
表将包含user_id
和role_id
,没有别的。例如,对于像这样的表,Java中没有类表示。这通常是@ManyToMany
,两边都有Collection
。
我在另一个答案(Hibernate : Opinions in Composite PK vs Surrogate PK)中分享了我对自然键与代理键的看法,我相信复合键与自然键有一些共同点,但没有带来任何实际好处。
复合键的问题在于,您需要两个值来唯一标识记录。一旦开始具有引用第一个表中的记录的表,这就成了问题。然后第二个表需要两个列才能引用一个记录。如果第二个表使用由单个值+外键组成的复合键,则现在有三个列来唯一标识一个记录。第三个表需要这些三个额外列,以便在第二个表中引用一个记录。真的,这是一个雪球。
另一个缺点是需求做会发生变化。每时每刻。因此,今天似乎是一个好的复合键并不是明天的关键。这就是为什么我们有代理键:为了面向未来。
主要使用复合键,以便表中的记录基于一组列是唯一的。例如,如果您有Customers
表,则可能会将NationalId
+ Country
作为唯一值,这意味着如果两个用户的国家/地区是美国,则他们无法共享相同的SSN。但如果两个记录不在同一个国家/地区,则可以使用相同的数字。如果你喜欢复合键,这将是一个很好的选择。但正如我之前所暗示的那样,您可以使用代理键并应用unique
约束。您将获得复合键的好处以及代理键的安全性。
答案 1 :(得分:3)
我无法想到您需要使用复合键的任何条件。使用单个id列的一些参数 Pro 包括:
1.更好的索引
2.更简单的连接
3.更容易设计guis
4.大多数ORM在单场PK中工作得更好(不幸的是)
5.更容易删除记录
在您的情况下,虽然您可以在person_id
和book_id
上使用复合/代理键并且它非常有用,但您也可以拥有一个 CAN 也是你的主键,但它不一定是。您可以将person_id
和book_id
用作PK或仅使用索引,对于id列也可以使用相同的值。 id
列可让您在删除内容或选择单列进行查看时更轻松。使用今天的RDBMS,您通常不必担心表大小,建议在所有表中包含一列 - 最好是自动增量标识列,以防万一需要。我相信它不会以任何方式伤害你。
答案 2 :(得分:0)
如果您正在存储一对一的人和书之间的关系(例如,您可能正在运行一个网站,用户可以按照1-5的等级对其阅读的书进行评分),那么votes
和person_id
book_id
表上的复合主键与(person_id, book_id)
的组合具有生成的ID和唯一索引一样有意义(如果不是更多) }。人和书的组合定义投票记录。
答案 3 :(得分:0)
代理密钥本质上是不好的,应该不惜一切代价避免。它们在现实世界中毫无意义。但有时它们是必要的。
暂时搁置一旁,你的例子说明了为什么需要复合键 - 不止一个人可以拥有一本特定书的副本 - 而一个人可以拥有多本书 - 这是一个N:M的关系。在关系数据库中表示这一点很简单:你把另一张表放在中间,带有书的PK和人的PK。
id,person_id,book_id
但是(除非您想要满足您需要区分同一个人拥有的同一本书的2个副本的情况,在这种情况下,架构需要其他几个更改),因为person_id和book_id的组合已经是唯一的,为什么还需要另一个与您尝试建模的数据无关的唯一标识符。