相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  使用多个表

5.3.4.9 使用多个表

pet 表跟踪你拥有的宠物。如果你想记录有关它们的更多信息,例如它们生命中的事件(例如去看兽医或产仔),你需要另一个表。这个表应该是什么样的?它需要包含以下信息

  • 宠物名称,以便你知道每个事件属于哪只动物。

  • 日期,以便你知道事件发生的时间。

  • 一个描述事件的字段。

  • 一个事件类型字段,如果你想能够对事件进行分类。

考虑到这些因素,CREATE TABLE 语句用于 event 表可能如下所示

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
       type VARCHAR(15), remark VARCHAR(255));

pet 表一样,最简单的方法是创建一个包含以下信息的制表符分隔的文本文件来加载初始记录。

name date type remark
Fluffy 1995-05-15 litter 4 kittens, 3 female, 1 male
Buffy 1993-06-23 litter 5 puppies, 2 female, 3 male
Buffy 1994-06-19 litter 3 puppies, 3 female
Chirpy 1999-03-21 vet needed beak straightened
Slim 1997-08-03 vet broken rib
Bowser 1991-10-12 kennel
Fang 1991-10-12 kennel
Fang 1998-08-28 birthday Gave him a new chew toy
Claws 1998-03-17 birthday Gave him a new flea collar
Whistler 1998-12-09 birthday First birthday

加载记录如下

mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;

根据你从在 pet 表上运行的查询中学习到的知识,你应该能够对 event 表中的记录执行检索;原理是一样的。但是,什么时候 event 表本身不足以回答你可能会问的问题?

假设你想找出每只宠物产仔时的年龄。我们之前已经了解了如何从两个日期计算年龄。母亲的产仔日期在 event 表中,但要计算她在那个日期的年龄,你需要她的出生日期,它存储在 pet 表中。这意味着查询需要两个表

mysql> SELECT pet.name,
       TIMESTAMPDIFF(YEAR,birth,date) AS age,
       remark
       FROM pet INNER JOIN event
         ON pet.name = event.name
       WHERE event.type = 'litter';
+--------+------+-----------------------------+
| name   | age  | remark                      |
+--------+------+-----------------------------+
| Fluffy |    2 | 4 kittens, 3 female, 1 male |
| Buffy  |    4 | 5 puppies, 2 female, 3 male |
| Buffy  |    5 | 3 puppies, 3 female         |
+--------+------+-----------------------------+

关于此查询,需要注意以下几点

  • FROM 子句连接两个表,因为查询需要从两个表中提取信息。

  • 在组合(连接)来自多个表的信息时,你需要指定如何将一个表中的记录与另一个表中的记录匹配起来。这很容易,因为它们都有一个 name 列。查询使用 ON 子句根据 name 值匹配两个表中的记录。

    查询使用 INNER JOIN 来组合表。INNER JOIN 允许来自任一表的行出现在结果中,当且仅当两个表都满足 ON 子句中指定的条件。在这个例子中,ON 子句指定 pet 表中的 name 列必须与 event 表中的 name 列匹配。如果一个名称出现在一个表中,但在另一个表中没有出现,则该行不会出现在结果中,因为 ON 子句中的条件失败。

  • 因为 name 列出现在两个表中,所以你在引用该列时必须明确说明指的是哪个表。这可以通过在列名前添加表名来完成。

你不需要有两个不同的表来执行连接。有时,如果你想将表中的记录与同一个表中的其他记录进行比较,将表与自身连接非常有用。例如,要查找宠物中的繁殖对,你可以将 pet 表与自身连接,以生成相同物种的活雄性和雌性的候选对

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
       FROM pet AS p1 INNER JOIN pet AS p2
         ON p1.species = p2.species
         AND p1.sex = 'f' AND p1.death IS NULL
         AND p2.sex = 'm' AND p2.death IS NULL;
+--------+------+-------+------+---------+
| name   | sex  | name  | sex  | species |
+--------+------+-------+------+---------+
| Fluffy | f    | Claws | m    | cat     |
| Buffy  | f    | Fang  | m    | dog     |
+--------+------+-------+------+---------+

在这个查询中,我们为表名指定了别名来引用列,并明确区分每个列引用关联的表的实例。