在什么条件下我们需要在数据库中使用复合键

我已经看到我们可以有复合键,其中主键由两个表的组合主键组成。

喜欢人和书

person_id and book_id will make the primary key. 

但我想问一下,我们需要硬编码编程语言

我的意思是,它可以,我可以有任何名称的单独列作为主键,然后我不必硬编码它,我可以像往常一样执行我的function

 id,person_id ,book_id 

在“新”应用程序中永远不应考虑复合键。 过去曾经使用它们的人曾经认为“商业钥匙”比“代理钥匙”更好。

编辑:正如克里斯所问,我正在扩大我的答案。

首先让我说明我将这个问题理解为“复合主键”与“代理键”。

此外,我承认有一个用例,其中复合键是有意义的:在交叉引用表中,也称为“链接表”。 它们用于多对多表中,并且只包含两个字段,这两个字段都是形成外部参照表主键的外键。 例如, UserRole表将包含user_idrole_id ,没有别的。 例如,对于像这样的表,Java中没有类表示。 这通常是@ManyToMany ,双方都有一个Collection

我在另一个答案中分享了我对自然键与代理键的看法( Hibernate:复合PK与Surrogate PK中的意见 ),我相信复合键分享了自然键的一些缺点,没有带来任何实际好处。

复合键的问题是您需要两个值来唯一标识记录。 一旦开始具有引用第一个表中的记录的表,这就成了问题。 然后第二个表需要列才能引用一条记录。 如果第二个表使用由单个值+外键组成的复合键,则现在有列可唯一标识一个记录。 第三个表需要这三个额外的列才能引用第二个表中的一个记录。 真的,这是一个雪球。

另一个缺点是需求确实发生变化。 每时每刻。 因此,今天似乎是一个好的复合键并不是明天的关键。 这就是为什么我们有代理键:为了面向未来。

主要使用复合键,以便表中的记录基于一组列是唯一的。 例如,如果您有一个Customers表,您可能将NationalId + Country作为唯一值,这意味着如果两个用户的国家/地区是美国,则他们无法共享相同的SSN。 但如果两个记录不在同一个国家/地区,则可以使用相同的数字。 如果你喜欢复合键,这将是一个很好的选择。 但正如我先前所说,您可以使用代理键并应用unique约束。 您将获得复合键的好处以及代理键的安全性。

我想不出你需要使用复合键的任何条件。 Pro使用单个id列的一些参数包括:
1.更好的索引
2.更简单的连接
3.更容易设计guis
4.大多数ORM与单场PK更好地工作(不幸的是)
5.更容易删除记录

在你的情况下,虽然你可以在person_idbook_id上有一个复合/代理键,它会非常有用,你也可以有一个id列,它也可以作为你的主键,但它不一定是。 您可以将person_idbook_id用作PK或仅使用索引,对于id列也可以使用相同的值。 id列可以在删除内容或选择单个列进行查看时更轻松。 使用今天的RDBMS,您通常不必担心表大小,建议在所有表中包含一列 – 最好是自动增量标识列,以防万一需要。 我相信它不会以任何方式伤害你。

如果您要存储一对一的人和书之间的关系(例如,您可能正在运行一个网站,用户可以按照1-5的等级对其读取的书进行评分),那么复合主键在person_idbook_idvotes表上,如果不是更多,则在(person_id, book_id)的组合上具有生成的ID和唯一索引。 人与书的组合定义了投票记录。

代理键本质上是坏的,应该不惜一切代价避免。 它们在现实世界中毫无意义。 但有时它们是必要的。

暂且不谈这一点,你的例子说明了为什么需要复合键 – 不止一个人可以拥有一本特定书的副本 – 而一个人可以拥有多本书 – 它是一种N:M关系。 在关系数据库中表示这一点很简单:你将另一张表放在中间,其中包含书的PK和人的PK。

id,person_id,book_id

但是(除非您想要满足您需要区分同一个人拥有的同一本书的2个副本的情况,在这种情况下,模式需要其他几个更改),因为person_id和book_id的组合已经是唯一的,为什么呢?您需要另一个与您尝试建模的数据无关的唯一标识符。