虽然可以使用复合主键,但在下面的例子中,这真的是一种糟糕的做法吗?关于Stackoveflow seems to go both ways on this issue的共识.

为什么?


我想把订单的付款存储在一个单独的表中.原因是,一个订单可以有许多项,这些项以多对多关系的形式在单独的表中处理.现在,如果我不为我的支付表使用复合主键,我将丢失唯一的PaymentID:

[PaymentId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[OrderId] INT NOT NULL PRIMARY KEY --Also a Foreign Key--

现在,如果我删除OrderId的主键,我会失去一对一的关系,所以Many OrderIds can be associated to many PaymentIds,我不想要这个.

这似乎就是为什么其他答案(大部分)认为复合键是个坏主意的原因.如果不好,那么最好的做法是什么?

推荐答案

没有结论表明复合主键是不好的.

最佳做法是有some个或多个列唯一标识一行.但在某些表中,单靠一列本身不足以唯一标识一行.

SQL(和关系模型)允许使用复合主键.在某些情况下,这是一种很好的做法.或者,从另一个Angular 来看,这并非在所有情况下都是一种糟糕的做法.

有些人认为every表应该有一个自动生成唯一值的整数列,并且应该作为主键.有些人还声称,这个主键列应该始终称为id.但这些都是conventions种,不一定是最佳做法.约定有一些好处,因为它简化了某些决策.但公约也有限制性.

你的订单可能有多笔付款,因为有些人购买on layaway,或者他们有多个付款来源(例如,两张信用卡),或者两个不同的人想要支付一份订单(我经常和一个朋友去餐馆,我们每个人都支付自己的餐费,所以工作人员用我们的信用卡处理一半订单).

我将按照以下方式设计您描述的系统:

Products  : product_id (PK)

Orders    : order_id (PK)

LineItems : product_id is (FK) to Products
            order_id is (FK) to Orders
            (product_id, order_id) is (PK)

Payments  : order_id (FK)
            payment_id - ordinal for each order_id
            (order_id, payment_id) is (PK)

这也与identifying relationship的概念有关.如果定义付款的存在只是因为订单的存在,那么将订单作为主键的一部分.

请注意,LineItems表也缺少自己的自动递增单列主键.多对多表是一个很好地使用复合主键的classic 示例.

Sql相关问答推荐

每月有多少客户在 STORE 1 首次购买?

AWS Athena 使用 AND 条件查询 JSON 数组

使用 SQL Server 将列转换为多行

如何获得给定时间段的最小值

根据状态获取表中的特定数据

SQL 查询通过其特定的最新操作查找用户

dateadd 函数snowflake中的变量

假设星期从星期一开始,从 PostgreSQL 的日期字段中提取星期几

SQL Server 如果存在则 1 否则 2

如何在一个 PostgreSQL 查询中使用多个 WITH 语句?

TypeError:元组索引必须是整数,而不是 str

无法删除表用户,因为其他对象依赖于它

查询、本机查询、命名查询和类型查询之间的区别

postgresql - 查看架构权限

使用 ActiveRecord 进行 GROUP BY 和 COUNT

Teradata 中的 ROWS UNBOUNDED PRECEDING 用于什么?

如何使用一个 SQL 查询从数据库中删除所有表?

如何列出 PostgreSQL 上的活动连接?

使用 ActiveRecord 和 Yii2 记录实际的 SQL 查询?

通过搜索 SQL Server 中的所有表来查找字符串