可以将复合键设置为另一个表的主键吗?

时间:2010-02-22 21:08:49

标签: database-design primary-key composite-key

是否可以将复合键设置为另一个表的主键?

例如我有表:

  • Books - 使用主键:Product_ID
  • Client - 使用主键:Client_ID
  • Clients_Books - 使用复合主键:Product_IdClient_ID

我想将此复合主键从Clients_Books设置为另一个名为Order_Details的表的主键。但我不想使用Books,Clients表中的Product_ID和Client_ID。

这有意义吗?所有意见都非常受欢迎。

2 个答案:

答案 0 :(得分:1)

你走在一条黑暗而肮脏的道路上。不要这样做。坚持最佳实践 - 在表上使用一个简单的主键,然后在必要时为其他表提供一个外键。

答案 1 :(得分:1)

简短的回答是,不 - 不能那样做。 PK(或其他备用键)中的所有列都必须出现在FK定义中。还要记住,一个表可以有多个键 - 称为候选键(有时是备用键)。主键只是设计/使用的“最佳”键(通常是最窄的 - 字节大小最小)。我们将这些其他唯一索引的名称加上前缀“AK_ {name}” - AK = Alternate Key。

在这种情况下我们做的是两件事之一:

  1. 将合成的PK定义为“标识”列,然后将唯一索引添加到复合键 - 因此在表上有两个“键”。然后,所有子表都将FK定义为指向合成的Identity PK列。
  2. 保持复合键不变。将其定义为该主表上的PK,并使所有FK具有相同的定义。
  3. 通常,使用具有相同PK定义的多个表(即,也是另一个表的FK的PK)并不是一个好主意。我说“一般” - 理解你的实体的定义很重要。

    那么为什么要使用#1?我问自己的问题是复合键是否真的是定义行的数据?这个复合键真的是一行的定义还是更像是其他数据的FK?如果它更像是FK,那么我创建合成的PK(身份)。订单真的是客户拥有的书吗?订单可能会导致客户拥有一本新书 - 但它们可能不是一回事。

    在未来几年中,合成PK将为您提供更多选择。如果需要在Client_Books表中更改关系,则可以将更改隔离到其他表。

    例如 - 如果客户可以拥有多本书的副本,您将如何实施?使用合成键,您可以简单地删除复合键上的唯一索引并将其保留为简单的FK,然后Order_Details表将表示客户何时购买了第二个副本。但是,如果您在Orders路径上使用了复合键,那么您必须弄清楚如何重新定义Order_Detail以及Client_Books(以及指向Order_Detail的任何其他FK)。

    我还会要求您评估Order_Detail是否真的是Client_Book?通常,订单会导致客户拥有一本新书。我认为Orders独立于库存 - 因此Order_Detail上的PK不应该是Client_Books上的PK,Order_Detail可能应该拥有它自己的独立PK。