外鍵是關系型數據庫維護數據完整性的核心機制。MySQL 中僅 InnoDB 支持外鍵,本文系統梳理使用條件、定義語法、五種級聯動作、ALTER TABLE 增刪操作,並通過「大哥/小弟」實戰案例演示約束生效與級聯刪除/更新行為。
INT 對應 TINYINT 可,INT 對應 CHAR 不可。[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
可在 CREATE TABLE 或 ALTER TABLE 時使用。未指定 CONSTRAINT symbol 時 MySQL 自動生成名稱。
| 動作 | 行為 | InnoDB 支持 |
|---|---|---|
| RESTRICT | 拒絕父表刪除/更新(默認) | ✓ |
| CASCADE | 級聯刪除/更新子表匹配行 | ✓ |
| SET NULL | 子表外鍵列置 NULL(列需允許 NULL) | ✓ |
| NO ACTION | 同 RESTRICT,標準 SQL 語法 | ✓ |
| SET DEFAULT | 子表外鍵列置默認值 | ✗ 不支持 |
常見組合:
ON UPDATE CASCADE ON DELETE RESTRICTON UPDATE CASCADE ON DELETE CASCADE# 添加外鍵 ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE ...] [ON UPDATE ...] # 刪除外鍵 ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;
CREATE TABLE `dage` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE `xiaodi` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dage_id` int(11) DEFAULT NULL, `name` varchar(32) DEFAULT '', PRIMARY KEY (`id`), KEY `dage_id` (`dage_id`), CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`dage_id`) REFERENCES `dage` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
場景 1:默認 RESTRICT
INSERT INTO dage(name) VALUES('銅鑼灣'); -- id=1
INSERT INTO xiaodi(dage_id,name) VALUES(1,'銅鑼灣_小弟A');
DELETE FROM dage WHERE id=1;
-- ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
場景 2:插入不存在的外鍵值
INSERT INTO xiaodi(dage_id,name) VALUES(2,'旺角_小弟A'); -- ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
場景 3:改為 CASCADE 後級聯刪除
ALTER TABLE xiaodi DROP FOREIGN KEY xiaodi_ibfk_1; ALTER TABLE xiaodi ADD FOREIGN KEY(dage_id) REFERENCES dage(id) ON DELETE CASCADE ON UPDATE CASCADE; DELETE FROM dage WHERE id=1; -- Query OK, 1 row affected SELECT * FROM xiaodi; -- Empty set
外鍵約束讓數據庫層面自動維護引用完整性,減少應用代碼邏輯錯誤,但在高並發寫入場景下需評估鎖競爭影響,合理選擇級聯策略。