思考具有两个外键的一对多或多对多关系的正确方法是啥?

Posted

技术标签:

【中文标题】思考具有两个外键的一对多或多对多关系的正确方法是啥?【英文标题】:What is the correct way to think about a one-to-many or many-to-many relationship with two foreign keys?思考具有两个外键的一对多或多对多关系的正确方法是什么? 【发布时间】:2021-09-24 21:47:35 【问题描述】:

我有一个User 和一个Transaction 表:

用户

user_id (primary key)  
...

交易

transaction_id (primary_key)  
sender_id (foreign key)  
receiver_id (foreign key)    
...

应该如何看待这个问题?通常在一对多的情况下,我会说,“一个用户可以有很多事务,但一个事务只能有一个用户。”在这种情况下,一个事务需要两个用户。这是否是多对多?

【问题讨论】:

当您在指定基数时引用实体时,您需要考虑实体及其角色,而不是作为一个类。因此发送者和接收者是同一域的不同实体,这将导致两个 N 对 1 关系:每一方一个 【参考方案1】:

每对表之间可以有多个关系是很正常的。您应该分别对每一个词进行表述。

在这种情况下,您有两个一对多关系。我见过有五六个的案例。

比如有一个需求,支付记录需要包含所有参与其中的用户,解决方案是在用户表中添加六个外键:

谁输入了付款。 谁验证了它。 谁授权的。 对于超过 10,000 美元的付款,有第二个人进行授权。 谁处理了双周付款流程。 谁打印了支票。

要求将所有这些用户作为付款记录的一部分。在paymentuser 之间可以看到六个FK。

【讨论】:

【参考方案2】:

描述了从单个实体到另一个单个实体的关系。

在你的例子中,

一个用户 (from) 有零到多个 (0:M) 事务 (to) 交易(发件人)始终有一个 (1:1) 发件人用户(收件人) 交易(发件人)始终有一个 (1:1) 接收用户(收件人)

不要在一个陈述中描述关系的两端,因为这可能会导致混淆或忽略细节。如果切换“from”实体,实际上是在讨论不同的关系。

附带说明,我建议您将列命名为 sender_userId/receiver_userId 或类似名称。包括相关的实体名称可以帮助您稍后导航您的结构。随着设计内容的增长,sender_id/receiver_id 可能不会明显指向 User 实体。稍后的开发人员可能会开始寻找发送者实体等。

【讨论】:

以上是关于思考具有两个外键的一对多或多对多关系的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

mysql外键的三种关系

多对多、一对多或多对一

数据库设计中一对多对多对多关系依据外键的实现条件及方法

外键的变种 三种关系

JPA的一对多,多对多用法

关于JPA一对一,一对多(多对一),多对多的详解