一般规则是“使您的密钥尽可能窄,除非您明确要求扩展它们”。
典型情况
按照您的示例,当您开始设计OrderDetails
表格时,使用设计 1 您的选择是:
- 将整个 PK 迁移
OrderId, UserId
到子表中,或
- 在表中引入一些单列备用键
Orders
,并引用此 AK,而不是 PK。
如果您确实需要订单详细信息中的用户(这极不可能),则前一个模式很好,但您可能不需要。此外,如果您需要实现诸如“更改订单所有权”之类的功能,使用第一种方法时,您会发现任务突然变得比通常应有的复杂得多。
因此,在绝大多数情况下,后一种设计是可行的。
极端情况
假设你有一些特殊的业务需求,比如:
对于每个用户,订单号应该形成一个独立于任何其他用户订单的序列。
看起来像是设计 1 的合理理由,不是吗?嗯,是的,也不是。当然,您必须创建一个复合键UserId, OrderId
,以便不同用户可以重用订单号,但是:
- 这样的键不必是主键。此外,您不必通过子表中的任何外键来引用它。只需创建一个代理
Id bigint identity(1,1) primary key
并从任何地方引用它。
- “不更新密钥,或者至少不引用可更新密钥”的规则仍然有效。如果键可能是可更新的,那么它是一个非常差的被外键引用的候选者。