外鍵約束定義父表(被引用表)記錄變更時,子表(引用表)的聯動行為。MySQL 支援四種動作,本文通過對比表與實例闡述差異。
| 動作 | ON DELETE 行為 | ON UPDATE 行為 | 前提條件 |
|---|---|---|---|
| RESTRICT | 檢查子表有無引用,有則**拒絕刪除**父表行 | 檢查子表有無引用,有則**拒絕更新**父表主鍵 | 無 |
| NO ACTION | 標準 SQL 語義,**等同 RESTRICT**(MySQL 內部同義) | 等同 RESTRICT | 無 |
| CASCADE | **級聯刪除**子表對應行 | **級聯更新**子表外鍵值 | 無 |
| SET NULL | 子表外鍵列**置 NULL** | 子表外鍵列**置 NULL** | 外鍵列必須允許 NULL |
CREATE TABLE users (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
) ENGINE=InnoDB;
CREATE TABLE orders (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
user_id INT UNSIGNED,
amount DECIMAL(10,2),
CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO users (name) VALUES ('Alice'), ('Bob');
INSERT INTO orders (user_id, amount) VALUES (1, 100), (1, 200), (2, 50);
-- 1. CASCADE DELETE
DELETE FROM users WHERE id = 1;
-- orders 中 user_id=1 的兩筆自動刪除
-- 2. CASCADE UPDATE
UPDATE users SET id = 10 WHERE id = 2;
-- orders 中 user_id=2 自動更新為 10
-- 3. 若改為 SET NULL(需 ALTER TABLE 修改約束)
-- DELETE FROM users WHERE id = 10; → orders.user_id 變 NULL
-- UPDATE users SET id = 20 WHERE id = 10; → orders.user_id 變 NULL
NO ACTION 檢查延遲到**所有約束檢查之後**;RESTRICT **立即檢查**、優先級最高。ON DELETE RESTRICT,防止誤刪主體導致資料孤兒;業務層軟刪除(is_deleted=1)替代物理刪除。ON DELETE SET NULL,保留子表記錄但切斷關聯。ON DELETE CASCADE,主體消失從體必亡。ON UPDATE CASCADE 可防止手工修改主鍵導致不一致;但**主鍵一旦生成應不可變**,建議 RESTRICT。SET FOREIGN_KEY_CHECKS=0 可暫時關閉檢查(匯入資料時),操作完必須 =1。外鍵是資料完整性的守門員,用對動作能讓業務邏輯在資料庫層自動兜底;用錯則可能引發級聯風暴。