多对多 - 介绍¶
我们了解了如何在数据中使用一对多关系。
但如何处理多对多关系呢?
让我们来探索它们。🚀
从一对多开始¶
让我们从熟悉的、更简单的一对多选项开始。
我们有一个团队表和一个英雄表,对于每一个一个团队,我们可以有多个英雄。
由于每个团队可以有多个英雄,我们无法在team表中为所有英雄的ID都设置列。
但由于每个英雄只能属于一个团队,我们在英雄表中有一个单一列指向特定的团队(指向team表中的特定行)。
team表如下所示
| id | name | 总部 |
|---|---|---|
| 1 | 阻止者 | 锐利之塔 |
| 2 | Z-部队 | 玛格丽特修女酒吧 |
提示
请注意,它不包含任何指向其他表的外键。
而hero表如下所示
| id | name | secret_name | age | team_id |
|---|---|---|---|---|
| 1 | 死侍 | 戴夫·威尔逊 | 空 | 2 |
| 2 | 蜘蛛男孩 | 佩德罗·帕尔克多 | 空 | 1 |
| 3 | 锈人 | 汤米·夏普 | 48 | 1 |
我们在hero表中有一个team_id列,它指向team表中特定团队的ID。
这就是我们连接每个hero与team的方式
请注意,每个英雄只能有一个连接。但每个团队可以接收多个连接。特别是,团队Preventers有两个英雄。
引入多对多¶
但假设Deadpond是一个很棒的角色,他们把他招募到了新的Preventers团队,但他仍然是Z-Force团队的一部分。
所以,现在,我们需要让一个英雄能够连接到多个团队。然后,每个团队,仍然应该能够接收多个英雄。因此,我们需要一个多对多关系。
一个不太有效的简单方法是向hero表中添加更多列。想象一下我们添加了两列。现在我们可以将一个hero总共连接到3个团队,但不能更多。所以我们并没有真正解决支持多个团队的问题,而只是一个非常有限的固定数量的团队。
我们可以做得更好!🤓
链接表¶
我们可以创建另一个表,用于表示hero表和team表之间的链接。
此表仅包含两列:hero_id和team_id。
这两列都是外键,指向hero和team表中特定行的ID。
由于这表示英雄-团队-链接,我们将其命名为heroteamlink表。
它看起来像这样
请注意,现在hero表不再有team_id列,它被这个链接表取代了。
而team表,和以前一样,也没有任何外键。
具体来说,新的链接表heroteamlink将是
| hero_id | team_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
信息
此链接表的其他名称包括
- 关联表
- 辅助表
- 连接表
- 中间表
- 联合表
- 通过表
- 关系表
- 连接表
我使用“链接表”这个术语,因为它很短,不会与其他已使用的术语(例如“关系”)冲突,易于记忆如何书写,等等。
链接主键¶
好的,我们有一个只有两列的链接表。但请记住,SQL数据库要求每行都有一个主键,唯一标识该表中的行?
现在,这个表中的主键是什么?
我们如何识别每个唯一的行?
我们是否应该添加另一列作为这个链接表的主键?不!我们不必这样做。👌
这两列都是该表中每行的主键(而且每行只有这两列)。✨
主键是唯一标识单个表中特定行的一种方式。但它不一定是单个列。
主键可以是表中列的组合,这些组合在该表中是唯一的。
再次查看上面的表格,看到每行都有hero_id和team_id的唯一组合吗?
我们不能有重复的主键,这意味着我们不能有hero和team之间重复的链接,这正是我们想要的!
例如,数据库现在将阻止像这样带有重复行的错误
| hero_id | team_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| 3 🚨 | 1 🚨 |
英雄两次属于同一个团队是没有意义的,对吗?
现在,只需将这两列用作该表的主键,SQL就会阻止我们重复hero和team之间的链接。✅
回顾¶
一个带有回顾的介绍!这很奇怪……但无论如何。🤷
现在你已经掌握了多对多关系的理论,以及如何用SQL中的表来解决它们。🤓
现在让我们看看如何编写SQL和代码来处理它们。🚀