# P34 34. 基础-约束-外键约束

> 本页是学习笔记，不等同于视频逐字稿。原声字幕未取得（匿名接口字幕轨为空且需登录，未使用任何账号），也没有逐句讲解记录；讲义只按节与页码对应，切点未逐句确证。

> 以同版讲义的公开镜像核对章节与页码（镜像非官方出品）；非逐字稿，示例为原创补充。

## P34 34. 基础-约束-外键约束

- 原视频：https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=34（p=34），时长 10:14
- 讲义：4.3.1 外键介绍 / 4.3.2 外键语法 p64–66（公开镜像；按主题对应，切点 notexact）

- 本集练习数据：practice/p34.sql（先执行，再对照小例）

### 一句话理解

外键让子表的一列只能取父表里真实存在的值，从而不让“孤儿数据”进库。

### 跟播：视频里 ↔ 本站

视频用 emp（子表）与 dept（父表）讲外键，并说明这两张表在数据库层面其实没建约束。

| 视频里 / 原课字段 | 本站对应 |
|---|---|
| 讲义 dept：1 研发部、2 市场部（p65 原名） | 本页练习表同样用 1 研发部、2 市场部（沿用讲义原名） |
| 讲义 emp 6 行、含 job / entrydate | 本站 employee 4 行、5 列（没有 job / entrydate） |

看完应能：能说出子表父表方向，并知道插入不存在的父键会报 1452

P37 起换成本站另一套 6 列小表（2 号部门叫测试部），那是那一页的练习数据，不是这里写错。

### 步骤

1. 确定方向：employee.dept_id 指向 department.id，employee 是子表，department 是父表。没有外键时直接删父表一行，子表会留下指向不存在部门的孤儿数据，而且不报错——外键就是用来挡这个的。
2. 确认父表被引用的列有唯一索引（通常是主键），两边数据类型一致。
3. 建表时写 FOREIGN KEY (dept_id) REFERENCES department(id)，或建表后用 ALTER TABLE 补。
4. 插入一个父表不存在的 dept_id，确认被拒绝（错误 1452）。

### SQL 示例

```
ALTER TABLE employee
  ADD CONSTRAINT fk_employee_department
  FOREIGN KEY (dept_id) REFERENCES department (id);
```

说明：【原创演示】依赖两张练习表：department(id,name) 有 (1,'研发部')、(2,'市场部')；employee 就是前面那四行。加约束后，小林、小周、小陈的 dept_id 都能在父表找到；小李的 dept_id 是 NULL，外键不检查 NULL，所以也能留下。再插 dept_id=99 会报 1452 无法添加或更新子行。本页原创例已在隔离的 MySQL 8.0.46 测试实例执行通过（含被 1452 拒绝的那次插入）；也可以用 p34.sql 复现。

### 易错点

- 父表被引用列没有唯一索引：建外键直接失败（错误 1822），这不是数据问题而是索引问题。
- 子表里已经有对不上父表的旧数据：先加约束会失败，必须先清脏数据或补父表记录。
- 以为外键能挡所有错误值：NULL 不受外键检查，允许空就等于允许“没有部门”的行。

### 30 秒速记

子表引用父表唯一列；类型要一致；可建表时写也可 ALTER 补；NULL 不检查；违反报 1452。

### 自测

1. 为什么 department.id 必须是主键或唯一索引？
   - 答：外键要确认子表的值能唯一对应父表的一行；父表被引用列不唯一时无法判断指向哪条记录，数据库会直接拒绝建约束。
2. 小李 dept_id 为 NULL，加外键后会被删掉吗？
   - 答：不会。外键只校验非 NULL 的引用值，NULL 表示“没有引用”，可以存在于子表。

### 材料与来源

- [平台视频页] P34 原视频页（BV1Kr4y1i7ru） https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=34
- [官方文档] MySQL 8.0 Reference：FOREIGN KEY 约束 https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html

证据说明：按 t012/t020 帧核对：外键页给出概念“外键用来让两张表的数据之间建立连接，从而保证数据的一致性和完整性”，并用 emp（子表，dept_id）与 dept（父表，id）示意，页面明确注明“两张表在数据库层面并未建立外键关联”。正文沿用这个父子关系，但使用自己的练习表与数据，未声称与课堂 emp 表一致；无字幕。
