什么是数据库建模中的多对多关系?如何在数据库中实现这种关系?本文中的示例将回答这些问题。

多对多关系可能是在数据库中显示的最棘手的关系。因此,我在本文中的第一步将是解释它们是什么。然后,我将继续给你几个多对多关系的例子,使它们尽可能接近现实生活。最后,我将使用这些示例向您展示如何在关系数据库中实现多对多关系。

准备?让我们开始吧。

理论上的多对多关系

多对多(或 M:N)关系是三种数据库关系之一。另外两个是:

  • 一对一 (1:1) 关系
  • 一对多 (1:N) 关系

根据定义,多对多关系是指表中的多条记录与另一个表中的多条记录相关。在数据库中表示这种关系可能很棘手,因此我将在下面的示例中向您展示如何执行此操作。您可能还想阅读有关实体、属性以及如何定义它们的信息。我会经常使用这些概念,所以阅读这篇文章不会有什么坏处。

实践中的多对多关系

让我们继续看这三个例子。我将在 ER 图中显示这些多对多关系。

示例 1:大学数据库

在此示例中,您的任务是构建大学数据库。你刚刚开始,但你已经卡住了。你必须向教授和他们教授的科目展示,但你将如何做到这一点?

让我向您展示如何通过首先定义实体来表示这种关系。一个实体是professor,另一个是subject 。让我们检查一下这是否可能是多对多关系。一位教授可以教授一门或多门科目,但一门学科也可以由一位或多位教授教授。这似乎是一个 M:N 关系,所以这是你的逻辑模型应该是什么样子的:






mysql多对多关系表 数据库中多对多关系_数据库


 


professor实体具有以下属性:

  • id:教授的身份证;主要标识符 (PI)。
  • first_name:教授的名字。
  • last_name:教授的姓氏。

subject实体具有以下属性:

  • id:受试者的 ID;主要标识符 (PI)。
  • subject_name:使用者名称。

多对多关系并不理想。如果保留上述示例中的内容,则数据将被复制。例如,如果有一位教授教授六门科目,你会让他或她在表格中列出六次,每次都是针对不同的科目。这是非常低效的。那么,您将如何解决这两个实体之间的这种多对多关系呢?通过在模型中引入联结表。它将多对多关系解析为多个一对多关系。

让我们将此逻辑模型转换为物理数据模型,看看会发生什么。首先,实体professorsubject将成为表,其属性将是表的列。它应该看起来像这样:



mysql多对多关系表 数据库中多对多关系_数据库_02


如您所见,有一个名为professor_subject的新表。它包含以下属性:

  • professor_id:教授的 ID,它引用了professor中的id列。
  • subject_id:主题的 ID,它引用了subject中的id列。

professor_id列是表professor的外键。这同样适用于subject_id ;它是表 subject的外键。同时,professor_id、subject_id组合是表professor_subject的主键。

professor_id、subject_id列共同形成复合主键(即主键由两个或多个列组成)。此复合主键可确保可以将教授分配到一个主题一次。每对值 (professor_id、subject_id ) 在表中最多只能出现一次。受试者也是如此。每个可以分配给一个教授一次。复合键可确保属性组合的唯一性。

让我们检查一下联结表是否解决了多对多关系。一位教授只能被分配到同一学科一次。另一方面,一个科目只能分配给同一位教授一次。似乎连接表达到了它的目的。

让我们转到下一个示例。这有点复杂,但不要害怕!

示例 2:产品订购数据库

在此示例中,您的任务是创建一个数据库,该数据库将帮助公司存储有关其供应商的信息。该数据库还将包含有关从供应商订购的所有产品/服务的信息。逻辑数据模型可能如下所示:



mysql多对多关系表 数据库中多对多关系_多对多_03


 


再一次,我们有两个实体:

  • supplier
  • product

supplier实体中,有四个属性:

  • id:供应商的身份证;主要标识符 (PI)。
  • supplier_name:供应商的名称。
  • supplier_address:供应商的地址。
  • supplier_country:供应商所在的国家/地区。

product实体中的属性如下所示:

  • id: 商品编号;主要标识符 (PI)。
  • product_name:产品名称。
  • product_description:产品描述。
  • price_per_unit:商品单价。

这两个实体之间的关系又是多对多的。可以从一个供应商处订购一种或多种产品。同时,公司可以从许多供应商处订购相同的产品,例如来自不同律师事务所的服务,来自不同制造商的轮胎等。当转换为关系数据库模型时,此逻辑模型的外观如何?如下:



mysql多对多关系表 数据库中多对多关系_数据库_04


 


再一次,不是多对多,而是自动命名为 supplier_product的新表。它只有两个属性:

  • supplier_id:引用supplier表中的 id 列。
  • product_id:引用product表中的 id 列。

同样,supplier_id、product_id对是supplier_product表的主键。但是,这可能还不够!如果任务是创建一个数据库来记录来自供应商的订单,那么最好稍微扩展一下表格,就像我在下面所做的那样:



mysql多对多关系表 数据库中多对多关系_数据库_05


现在看起来好多了!首先,我将表的名称更改为更具描述性的名称;它现在被命名为order .我还向表中添加了几个新属性。它由以下部分组成:


  • order_id:来自供应商的此订单的 ID 和表的主键 (PK)。
  • supplier_id:供应商的身份证;引用表 supplier
  • product_id:订购产品的ID;引用表 product
  • order_date:订单的日期。
  • quantity:订购的项目数。
  • total_price:订购产品的总价值。
  • status:订单的状态。

请记住,创建联结表时有两种可能性。一个是它只包含引用其他表的外键,这种情况经常发生。但是,有时联结表会成为其自己的实体,如本例中所示,联结表还包含其他属性。您应该始终使模型适应您的需求。

如果您想在类似示例中进行更多练习,请参阅此文章

现在你已经变得如此擅长这一点,让我们再看一个例子!

示例 3:图书出版商数据库

在此示例中,您从事出版业务,需要维护已出版书籍的记录。许多人都参与制作一本书,所以你也想记录这些人和他们的角色。逻辑模型可能如下所示:



mysql多对多关系表 数据库中多对多关系_多对多_06


这一次,有三个实体:


  • book
  • staff
  • role

book实体包含以下属性:

  • isbn:国际标准书号,用于书籍的主要标识符 (PI)。
  • title:书名。
  • issue:书籍的发行(即版本)(例如首次印刷,第一版等)。
  • date:问题的日期。

下一个实体是staff

  • id:工作人员的唯一身份证;主要标识符 (PI)。
  • first_name:工作人员的名字。
  • last_name:工作人员的姓氏。

在这两个实体之间,存在着多对多的关系。让我们检查一下逻辑。一名工作人员可以处理一本或多本书。一本书可以由一个人(嗯,很难)或由许多人处理。似乎关系逻辑有效!

在第三个实体上,role!它包括:

  • id:角色的 ID;主要标识符 (PI)。
  • role_name:角色的名称。
  • role_description:该角色的说明。

同样,实体staffrole 之间存在多对多关系。逻辑上说,一个工作人员在写一本书时可以填补一个或多个角色,一个角色可以由一个或多个工作人员执行。当我说角色时,我的意思是作者,合著者,编辑,校对员,翻译,插画家等。例如,一本书的作者也可以是另一本书的插画家,第三本书的翻译,第四本书的校对员。

这个例子似乎比前两个例子更复杂。到目前为止,逻辑模型中只有两个表。在这种情况下,物理模型的外观如何?喜欢这个:



mysql多对多关系表 数据库中多对多关系_主键_07


这看起来很可怕吗?嗯,也许有一点点。这里发生的事情是,你在不知情的情况下被介绍给三元关系。三元关系是指三个实体参与该关系,如本例所示。在这里,联结表再次具有由外键组成的复合主键。但是,这一次,主键由三列组成,而不是两列。


book表在这里很重要;这是必须确定本书创作者的起点。当我说创作者时,我指的是参与这本书的工作人员以及他们在那本书中的角色。

接下来,让我们分析一下交汇表book_creators。它有三个属性:

  • book_isbn:书籍的国际标准书号;引用book表。
  • staff_id:工作人员的身份证;引用staff表。
  • role_id:角色的 ID;引用role表。

表的主键是属性 book_isbnstaff_idrole_id 的唯一组合。

通过创建此联结表,您已经解决了多对多关系,这足以声明此任务已完成!

你对多对多关系有什么看法?

在这三个示例中,我试图向您展示逻辑数据库模型中的多对多关系。我们还讨论了如何处理物理数据模型。您已经了解到,关系数据库中的多对多关系可以通过实现联结表来解决。最后,我们还演示了您不必分别绘制逻辑模型和物理模型。