关联两个表时,应该做复合键,还是单独做primary/foreign键?

When relating two tables, should you do a composite key, or primary/foreign key separately?

表示两个 table 之间关系的行业设计标准是什么?您应该使用组合键,还是主键和外键分开?这两个选项之间是否存在性能差异?

例如,假设您有一个用户,该用户可以有零个或多个订单。您的用户 table 具有属性 PK UserIDName。没有用户,订单将永远不存在。现在,这就是我的问题所在......

  1. 你是不是按照第一张图,在OrderIDUserID之间使用了复合键?

  2. 或者,您是否遵循第二张图,其中没有复合键,订单仅由 OrderIDFK UserID 标识给用户 table?

一般规则是"keep your keys as narrow as possible, unless you have an explicit requirement to expand them"。

典型情况

按照您的示例,当您开始设计 OrderDetails table 时,对于设计 1,您的选择是:

  1. 将整个 PK OrderId, UserId 迁移到子 table 或
  2. Orders table 中引入一些单列备用密钥,并引用此 AK,而不是 PK。

如果您确实需要订单详细信息中的用户(这种可能性极小),则前一个架构很好,但您可能不需要。此外,如果您需要实现类似 "change ownership of an order" 的功能,使用第一种方法您会发现任务突然变得比正常情况下更复杂。

因此,在绝大多数情况下,后一种设计是可行的。

极端情况

假设您有一些特殊的业务需求,例如:

For every user, orders' numbers should form a sequence independent from orders of any other users.

看起来设计 1 的理由很合理,不是吗?好吧,是的,不是。当然,您必须创建一个由 UserId, OrderId 组成的复合键,以便不同用户可以重复使用订单号,但是:

  1. 这样的键不一定是主键。此外,您不必通过子 table 中的任何外键引用它。只需创建一个代理 Id bigint identity(1,1) primary key 并从任何地方引用它。
  2. 规则"don't update keys, or at least don't reference updateable keys"仍然有效。如果密钥可能是可更新的,则它不太可能被外键引用。