首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >复合主键:好还是坏?

问复合主键:好还是坏?
EN

Stack Overflow用户
提问于 2014-09-27 19:46:55
回答 6查看 73.6K关注 0票数 75

虽然可以使用复合主键,但对于下面的情况,这真的是一种糟糕的做法吗?关于Stackoveflow的共识似乎在这个问题上是两全其美的。

为什么?

我想把订单的付款放在一个单独的桌子上。原因是,一个订单可以有多个项目,它们以多到多关系的形式在一个单独的表中处理。现在,如果我不使用复合主键作为我的支付表,我将失去我唯一的PaymentID

代码语言:javascript
复制
[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,我不想这样做。

这似乎就是为什么其他答案已经得出结论(主要是),复合键是一个不好的想法。如果是坏的,那么最好的做法是什么?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-09-27 19:58:01

没有结论认为复合主键是坏的。

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

SQL (和关系模型)允许组合主键。这是一个很好的做法,是一些案例。或者,另一种看法是,这并不是一个坏的做法,在所有的情况下。

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

您可能有一个带有多笔付款的订单,因为有些人购买了on layaway,或者他们有多个支付来源(例如,两张信用卡),或者两个不同的人想要支付订单中的一部分(我经常和朋友一起去餐厅,我们每个人都为自己的餐费买单,因此员工在我们的信用卡上处理订单的一半)。

我将设计您描述的系统如下:

代码语言:javascript
复制
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表也没有它自己的自动增量,单列主键。多对多表是一个很好地使用复合主键的典型例子。

票数 83
EN

Stack Overflow用户

发布于 2014-09-27 20:06:03

这个问题接近征求意见的危险,这可能引发宗教战争。作为高度倾向于在我的表中自动增加整数主键(称为TablenameId,而不是Id)的人,有一种情况是它是可选的。

我想其他答案说明了你为什么要主键。

一个非常重要的原因是供参考之用。在关系数据库中,任何实体--理论上--都可以通过外键关系被另一个实体引用。对于外键,您肯定需要一个列来唯一地定义行。否则,您必须处理不同表中对齐的多个列。这是可能的,但很麻烦。

您所指的表不是“实体”表,而是“连接”表。它是一个用于处理多到多关系的关系数据库结构。因为它并不真正代表一个实体,所以它不应该有外键关系。因此,复合主键是合理的。有些情况下,例如当您考虑数据库大小时,忽略一个人工主键甚至是可取的。

票数 32
EN

Stack Overflow用户

发布于 2017-02-21 12:10:16

磁盘空间很便宜,因此以约定(如pk +表名)命名的int标识(1,1)上的主键是一种很好的做法。它将使查询、联接、索引和其他约束更易于管理。

但是,有一个很好的理由不这样做(至少在MS中):如果您想管理底层存储系统中数据的物理排序。

主键群集决定物理排序顺序。如果在标识列上执行此操作,则物理排序顺序基本上是插入顺序。但是,这可能不是最好的,特别是如果您总是以相同的方式查询表的话。在非常大的表上,获得正确的物理排序顺序会使查询速度更快。例如,您可能需要两列组合的聚集索引。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26078535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档