📄 一句话概括
外键是表与表之间的挂钩:这一列的值必须是别表主键里真实存在的——不存在的班级编号插不进学生表,还带学生的班级也删不掉。它把「两张表对得上」从愿望变成铁律。
📝 本节和前面几节的关系
2-3 首次提出「外键=借来别表的主键」,3-21/3-22 用 JOIN 沿它连表——本节给它上约束这把锁。到本节为止,4-6 约束总图上的成员全部到齐;从 4-14 起,话题切换到另一路防线:事务。
一、没有外键约束的世界
-- 两张表:classes(1,2,3 班) 和 students
INSERT INTO students VALUES (1, '张三', 9); -- 9 班?根本不存在!照样插入成功
脏数据就这么进来了:JOIN 一查,张三人间蒸发(在 classes 表里找不到 9 班)。外键约束就是堵这个洞。
二、加锁后的两条铁律
CREATE TABLE classes (
id INT PRIMARY KEY,
name VARCHAR(20)
);
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(20),
class_id INT,
FOREIGN KEY (class_id) REFERENCES classes(id) -- 挂钩
);
- 插入/更新被管:students 的 class_id 只能填 classes 里真实存在的 id(填 9 → 报错)
- 删除/更新反向被管:classes 里还挂着学生的班删不掉(先处理学生,或定义级联规则)
三、级联:删除时的自动化选择
FOREIGN KEY (class_id) REFERENCES classes(id)
ON DELETE CASCADE -- 班级删,学生跟着删
-- 或 ON DELETE SET NULL / 默认 RESTRICT(拦住不让删)
| 规则 | 删班级时学生怎么办 |
|---|---|
RESTRICT(默认) |
不许删班,先疏散学生 |
CASCADE |
学生一起删(慎用!) |
SET NULL |
学生 class_id 置空 |
提示:SQLite 命令行默认不启用外键检查,要先执行 PRAGMA foreign_keys = ON; 才生效——Demo 里别忘了。
四、动手 Demo:插不进与删不掉
PRAGMA foreign_keys = ON; -- SQLite 必须先开(MySQL 自带开启)
CREATE TABLE classes (id INT PRIMARY KEY, name VARCHAR(20));
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(20),
class_id INT,
FOREIGN KEY (class_id) REFERENCES classes(id)
);
INSERT INTO classes VALUES (1, '一班');
INSERT INTO students VALUES (1, '张三', 1); -- 1 班存在,成功
INSERT INTO students VALUES (2, '李四', 9); -- 9 班不存在 → 报错
DELETE FROM classes WHERE id = 1; -- 班里还有张三 → 报错
DELETE FROM students WHERE id = 1; -- 先疏散学生
DELETE FROM classes WHERE id = 1; -- 现在删得掉了
五、30 秒实验
把 PRAGMA foreign_keys = ON; 注释掉重跑——两条报错全部变成「成功」,脏数据畅通无阻。约束要先打开才会执法,这是 SQLite 新手最常踩的静默坑。
六、常见误区
- 「外键会让查询变快」:外键是约束不是索引加速器(MySQL 会顺手建索引,但本质是防脏数据)
- 「删了学生就能删班级,多麻烦」:这正是价值——强制你先想清楚关系再动手,而不是留一堆孤儿数据
- 「JOIN 靠外键才连得上」:JOIN 语法上只要求值相等;外键约束保证连出来的关系是真实可信的
自测三问
1. 外键约束管住哪两个方向?(插入端只许填存在的值;删除端不许留下孤儿) 2. 三种级联规则分别是什么?(RESTRICT 拦住 / CASCADE 连坐删除 / SET NULL 置空) 3. SQLite 里外键不生效先干什么?(PRAGMA foreign_keys = ON)- ☐ 下一节(4-14 事务-集中执行无法分割的处理)
相关笔记
- PRIMARY KEY、主关键字、主键-使记录可以进行唯一识别 —— 上一节:外键借的就是主键
- 事务-集中执行无法分割的处理 —— 下一节:换一路防线
- 外连接、LEFT JOIN、RIGHT JOIN-获取标准记录及与之匹配的记录 —— 关系对不上时的兜底查询
- 🗄️ 数据库基础 · 索引 —— 全课路线图