外鍵是關聯式資料庫維護資料完整性的核心機制。本文詳細解析 MySQL 外鍵的使用條件、語法選項、級聯行為,並透過「大哥/小弟」實戰案例展示約束效果與異常處理。
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}]
CONSTRAINT symbol:約束名稱,省略時 MySQL 自動生成。ON DELETE / ON UPDATE:定義父表記錄異動時,子表的對應行為。
CREATE TABLE `dage` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(32) DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 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=utf8mb4;
-- 新增大哥
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
-- 嘗試新增不存在的大哥 ID → 失敗
INSERT INTO xiaodi(dage_id, name) VALUES(2, '旺角_小弟A');
-- ERROR 1452 (23000): Cannot add or update a child row
-- 刪除舊外鍵 ALTER TABLE xiaodi DROP FOREIGN KEY xiaodi_ibfk_1; -- 重新加入 CASCADE ALTER TABLE xiaodi ADD FOREIGN KEY (dage_id) REFERENCES dage(id) ON DELETE CASCADE ON UPDATE CASCADE;
DELETE FROM dage WHERE id=1; -- 成功,對應小弟記錄自動刪除 SELECT * FROM xiaodi; -- Empty set
CASCADE。SET FOREIGN_KEY_CHECKS=0;。結語:外鍵是資料完整性的守門員,善用 ON DELETE/UPDATE CASCADE 可大幅簡化應用層邏輯,但需權衡效能與維護複雜度。建議在設計階段明確界定業務語義,選擇適合的約束策略。