### 3.6.6 使用外键
在 MySQL 中, `InnoDB` 表支持检查外键约束. 参阅 [Chapter 15, InnoDB 存储引擎](https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html), 和 [Section 1.8.2.3, “外键差异”](https://dev.mysql.com/doc/refman/8.0/en/ansi-diff-foreign-keys.html).
外键约束不仅仅用于连接两个表. 除了 `InnoDB` 存储引擎, 在定义列时使用 `REFERENCES tbl_name(col_name)` 子句, 该句没有实际的效果, *只是作为一个备忘录或者注释告诉你当前定义的列是指的另外一张表的列*. 使用这种语法时, 认识到这一点非常重要:
- MySQL 不执行任何检查来确保 *col_name* 确实存在于 *tbl_name* (甚至 *tbl_name* 本身是否存在).
- MySQL 不会对 *tbl_name* 执行任何类型的操作, 例如删除行以响应对你定义的表中的行的响应; 换句话讲, 这个语法不会对 `ON DELETE or ON UPDATE` 行为产生任何影响. (虽然你可以将 `ON DELETE` 或者 `ON UPDATE` 子句作为 `REFERENCES` 子句的一部分, 但它被忽略.)
- 该语法创建一个*列*; 它***不***会创建任何索引或者键.
你可以创建列作为连接列, 如下所示:
```sql
CREATE TABLE person (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE shirt (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),
PRIMARY KEY (id)
);
INSERT INTO person VALUES (NULL, 'Antonio Paz');
SELECT @last := LAST_INSERT_ID();
INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', @last),
(NULL, 'dress', 'white', @last),
(NULL, 't-shirt', 'blue', @last);
INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');
SELECT @last := LAST_INSERT_ID();
INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', @last),
(NULL, 'polo', 'red', @last),
(NULL, 'dress', 'blue', @last),
(NULL, 't-shirt', 'white', @last);
SELECT * FROM person;
+----+---------------------+
| id | name |
+----+---------------------+
| 1 | Antonio Paz |
| 2 | Lilliana Angelovska |
+----+---------------------+
SELECT * FROM shirt;
+----+---------+--------+-------+
| id | style | color | owner |
+----+---------+--------+-------+
| 1 | polo | blue | 1 |
| 2 | dress | white | 1 |
| 3 | t-shirt | blue | 1 |
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
| 7 | t-shirt | white | 2 |
+----+---------+--------+-------+
SELECT s.* FROM person p INNER JOIN shirt s
ON s.owner = p.id
WHERE p.name LIKE 'Lilliana%'
AND s.color <> 'white';
+----+-------+--------+-------+
| id | style | color | owner |
+----+-------+--------+-------+
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
+----+-------+--------+-------+
```
当以这种方式使用时, `REFERENCES` 子句不会显示在 [SHOW CREATE TABLE](https://dev.mysql.com/doc/refman/8.0/en/show-create-table.html) or [DESCRIBE](https://dev.mysql.com/doc/refman/8.0/en/describe.html) 的输出中:
```sql
SHOW CREATE TABLE shirt\G
*************************** 1. row ***************************
Table: shirt
Create Table: CREATE TABLE `shirt` (
`id` smallint(5) unsigned NOT NULL auto_increment,
`style` enum('t-shirt','polo','dress') NOT NULL,
`color` enum('red','blue','orange','white','black') NOT NULL,
`owner` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4
```
按这种方式使用 `REFERENCES` 作为注释或者 “提示” 创建列适用于 `MyISAM` 表.
- 简介
- 前言和法律条款
- 安装和更新 MySQL
- 在 Linux 上安装 MySQL
- 在 Linux 上使用 APT 库安装 MySQL
- 在 Linux 上使用 Docker 部署 MySQL
- 使用 Docker 部署 MySQL 服务器的基本步骤
- 使用 Docker 部署 MySQL 服务器的更多主题
- 教程
- 连接到服务器和从服务器断开
- 输入查询
- 创建和使用数据库
- 创建和选择数据库
- 创建表
- 将数据加载到表中
- 从表中检索数据
- 选择所有数据
- 选择特定行
- 选择指定列
- 行排序
- 日期计算
- 处理 NULL 值
- 模式匹配
- 计算行数
- 使用多个表
- 获取数据库和表的信息
- 在批处理模式使用 mysql
- 常见查询示例
- 列的最大值
- 包含某一行最大值的记录
- 每组中列的最大值
- 拥有某个字段的组间最大值的行
- 使用用户自定义变量
- 使用外键
- 两个键上搜索
- 计算每日访问量
- 使用 AUTO_INCREMENT
- 在 Apache 中使用 MySQL
- MySQL 程序
- MySQL 客户端程序
- mysql — MySQL 命令行客户端
- 优化
- 优化概述
- 优化 SQL 语句
- 优化和索引
- 优化数据库结构
- 优化 InnoDB 表
- 优化 MyISAM 表
- 优化 MEMORY 表
- 理解查询执行计划
- 控制查询优化器
- 缓冲和缓存
- 优化锁操作
- 优化 MySQL 服务器
- 测量性能 (Benchmarking)
- 检查线程信息