外鍵維護父子表引用完整性。本文通過完整 DDL 演示,詳解 ON DELETE 四種行為、ON UPDATE 兩種行為,並強調父表列必須為主鍵(或唯一約束)的前置條件。
DROP TABLE student_class;
DROP TABLE student;
DROP TABLE class;
CREATE TABLE student (
student_id INTEGER NOT NULL,
student_name VARCHAR(200),
CONSTRAINT P_KEY_1 PRIMARY KEY (student_id)
) IN luzl_32k_tb INDEX IN luzl_32k_tb;
CREATE TABLE class (
class_id INTEGER NOT NULL,
class_name VARCHAR(200),
CONSTRAINT P_KEY_2 PRIMARY KEY (class_id)
) IN luzl_32k_tb INDEX IN luzl_32k_tb;
CREATE TABLE student_class (
student_class_id INTEGER,
student_id INTEGER,
class_id INTEGER
) IN luzl_32k_tb INDEX IN luzl_32k_tb;
-- 外鍵:班級
ALTER TABLE student_class
ADD CONSTRAINT if_class FOREIGN KEY (class_id)
REFERENCES class(class_id)
ON DELETE CASCADE
ON UPDATE RESTRICT;
-- 外鍵:學生
ALTER TABLE student_class
ADD CONSTRAINT if_student FOREIGN KEY (student_id)
REFERENCES student(student_id)
ON DELETE CASCADE
ON UPDATE RESTRICT;
-- 測試數據
INSERT INTO student VALUES (1, 'luzl');
INSERT INTO class VALUES (1, 'db2');
INSERT INTO student_class VALUES (1, 1, 1);
| 選項 | 行為 | 等價術語 | 典型場景 |
|---|---|---|---|
| RESTRICT | 存在子記錄時拒絕刪除父記錄,報錯 | NO ACTION(DB2 中語義相同) | 嚴格保護主數據,防誤刪 |
| NO ACTION | 同 RESTRICT,檢查時機為語句結束 | RESTRICT | 標準 SQL 兼容 |
| CASCADE | 刪除父記錄時自動級聯刪除所有關聯子記錄 | 級聯刪除 | 訂單-明細、班級-學生關係 |
| SET NULL | 刪除父記錄時,將子表關聯列置 NULL(需列允許 NULL) | — | 可選關聯,如員工-部門(可為空) |
注意:指定 CASCADE 或 NO ACTION/RESTRICT 時,若子表有數據,直接刪除父記錄會報錯(RESTRICT/NO ACTION)或級聯刪除(CASCADE)。SET NULL 允許刪除父記錄並置空子表外鍵列。
| 選項 | 行為 |
|---|---|
| RESTRICT | 存在子記錄時拒絕更新父表主鍵值 |
| NO ACTION | 同 RESTRICT,語句結束時檢查 |
DB2 不支持 ON UPDATE CASCADE/SET NULL。主鍵值一旦被引用,通常不應變更;業務確需變更時,需先處理子表數據(刪除/更新外鍵值),再更新父表主鍵。
父表引用列必須定義為 PRIMARY KEY 或 UNIQUE CONSTRAINT。示例中 student.student_id、class.class_id 均為主鍵,滿足條件。若父表列無唯一約束,ALTER TABLE ... ADD FOREIGN KEY 會報錯。
ON DELETE CASCADE,簡化應用邏輯。ON DELETE SET NULL,保留子記錄歷史。ON DELETE RESTRICT。ALTER TABLE ... FOREIGN KEY ... NOT ENFORCED,載畢後 ENFORCED 並 SET INTEGRITY 驗證。