-- 父表
CREATE TABLE parent (
id INT PRIMARY KEY,
name VARCHAR(50)
) ENGINE=InnoDB;
-- 子表建立外鍵
CREATE TABLE child (
id INT PRIMARY KEY,
parent_id INT,
data VARCHAR(100),
CONSTRAINT fk_child_parent
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
-- 或 ALTER TABLE 新增
ALTER TABLE child
ADD CONSTRAINT fk_child_parent
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE RESTRICT ON UPDATE RESTRICT;
| 動作 | 行為 | 適用場景 | 風險 |
|---|---|---|---|
| CASCADE | 父變 → 子同步變 (刪父刪子、改父改子) | 強關聯、生命週期綁定 (訂單-明細) | 誤刪父表導致大量子資料連鎖刪除 |
| SET NULL | 父變 → 子外鍵設 NULL (需欄位允許 NULL) | 弱關聯、子資料保留 (文章-分類) | 查詢需處理 NULL,語義變「未分類」 |
| SET DEFAULT | 父變 → 子外鍵設預設值 | 有明確預設分類/狀態 | MySQL 解析支援但**不執行**,實際同 RESTRICT |
| RESTRICT / NO ACTION | 父有子資料時禁止刪改 (預設) | 嚴格保護、需手動清理子資料 | 應用層需捕獲錯誤碼 1451/1452 |
mysqldump 預設導出外鍵定義,還原時需關閉檢查 SET FOREIGN_KEY_CHECKS=0;。
-- 查看表外鍵
SHOW CREATE TABLE child;
SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_NAME='child';
-- 臨時關閉外鍵檢查 (匯入/大量操作)
SET FOREIGN_KEY_CHECKS=0;
-- 操作完成
SET FOREIGN_KEY_CHECKS=1;
-- 刪除外鍵
ALTER TABLE child DROP FOREIGN KEY fk_child_parent;
CASCADE,配合應用層軟刪除 (is_deleted) 降低硬刪除風險。SET NULL,子表保留歷史資料。fk_子表_父表,便於 information_schema 查詢管理。InnoDB_row_lock_waits、InnoDB_deadlocks 指標。外鍵是資料完整性「最後防線」,但帶來鎖爭用、死鎖、遷移複雜度。**微服務/高併發架構傾向應用層保證完整性,資料庫層弱化外鍵**;單體應用、內部管理系統、報表庫則建議啟用外鍵降低業務邏輯複雜度。根據架構層級權衡選擇。