多对多关系中的重复主键

Posted

技术标签:

【中文标题】多对多关系中的重复主键【英文标题】:Duplicate primary keys in many-to-many relationship 【发布时间】:2020-02-04 05:21:02 【问题描述】:

tArticletCustomer 这两个表之间存在 m:n 关系。每当客户购买商品时,商品和客户之间的链接就会存储在第三个表中,其中包含包含客户购买金额的附加属性。

tArticle:

kArticle | title | stock
---------+-------+------
1        | Water | 39
2        | Apple | 14

tCustomer:

kCustomer | surname | firstName
----------+---------+----------
1         | Muller  | Max
2         | Meier   | Tom

tCustomer_tArticle:

kCustomer | kArticle | number
----------+----------+---------
1         | 2        | 2
2         | 2        | 5
2         | 2        | 3

我知道强烈建议您使用组合外键作为主键。但是因为同一个客户可以两次购买同一篇文章,这将不再是唯一的。

现在我的问题是我需要在第三个表中添加一个AUTO_INCREMENT 主键还是应该使用物理顺序来获得唯一记录。

我的第二个问题是,是否有办法在实体关系图中指定 m:n 关系中的链接是否可能出现两次。

【问题讨论】:

请在每个帖子中问一个问题,并且请不要问重复的问题,正如人们所预料的那样,这些都是重复的。 我认为您应该将此表重命名为 Orders 并添加 auto_increment 主键 - id,这样您的数据库中就可以有另一个需要使用 order_id 的表。 【参考方案1】:

“现在我的问题是我需要向第三个表添加一个 AUTO_INCREMENT 主键还是应该使用物理顺序来获得唯一记录。”

“具有唯一记录的物理顺序”是什么意思?

在你的情况下,我建议添加一个 AUTO_INCREMENT PK,比如:

order_id PRIMARY KEY AUTO_INCREMENT

我的理由是: 想想当你去麦当劳时,你会得到一张带有订单 ID 的收据。当您再次购买食物时,您将在新收据上获得不同的订单 ID。因此,order_id 属性使每个订单都是唯一的。

"如果有办法在实体关系图中指定 m:n 关系中的链接是否可能出现两次"

据我所知,没有。我假设您希望您的 E-R 模型反映多少次(或者客户可以多次购买同一商品),如果是这样,您可以按以下方式思考这个问题:

tCustomer_tArticle(order_id, kCustomer, kArticle, number) 能反映这个特性吗?是的。我们可以做到:

SELECT order_id,kCustomer,kArticle,number FROM tCustomer_tArticle WHERE kCustomer="Tom";

这将为我们提供 Tom 下了多少订单的结果。

只要你有一个PK来表明每个订单,你就会得到第二个问题的答案。

【讨论】:

如果我的回答没有解决您的问题,请随时发表评论【参考方案2】:

考虑您试图在 tCustomer_tArticle 表中表示哪些信息。例如以下情况:

kCustomer | kArticle | number
----------+----------+---------
2         | 2        | 3
2         | 2        | 3

这只是意味着汤姆买了六个苹果,还是意味着三个苹果各有两笔交易?如果表只是数量的记录,那么可以将kCustomer,kArticle作为key,一行记录相同的信息:

kCustomer | kArticle | number
----------+----------+---------
2         | 2        | 6

如果表应该记录单个事务,那么表中似乎缺少信息。鉴于您的原始示例包含三行样本数据,可能不清楚这是一个、两个还是三个事务。我希望有某种事务标识符作为复合键的一部分。我认为自动递增的数字不会有帮助。在考虑添加代理键之前,您需要先确定对业务领域有意义的有意义的键。

【讨论】:

【参考方案3】:

我不知道在哪里“强烈推荐”两个外键作为主键。在适当的情况下,这绝对是一种方法。我更喜欢始终为表分配唯一的自动递增键的方法,除非空间开销是一个大问题。自动递增键提供:

updates 和 deletes 对每一行的唯一引用。 广告订单记录。 可以向表声明更简单的外键。

本质上,您的表是一个事务表。我不仅会推荐自动递增的密钥,还会推荐交易日期/时间以及其他信息。

至于这条评论:

或者我应该使用物理订单来获得唯一的记录。

SQL 表代表无序 集合。您应该看到对访问行有用的物理顺序。如果您关心插入顺序,那么您确实需要一个自动递增的键。

【讨论】:

“我不知道在哪里“强烈推荐”两个外键作为主键”这取决于用例,但通常是M: N 对是唯一的,因此即使我们不希望将它们作为主要对象,我们也希望在它们上构建唯一键约束。但似乎 OP 的业务逻辑是不太常见的场景之一。

以上是关于多对多关系中的重复主键的主要内容,如果未能解决你的问题,请参考以下文章

Django 外键多对多插入数据方法

MySQL—多表关系

MySQL—多表关系

MySQL基础:多表查询

hibernate多对多

Hibernate的表之间的关系