Oracle 9i 引入 ON DELETE CASCADE 與 ON DELETE SET NULL 兩種 Referential Action,讓外鍵約束具備自動處理子表資料的能力,避免應用層手動維護級聯邏輯。本文以部門/員工經典模型實戰演示兩種模式差異、建立語法、約束條件與最佳實踐。
-- 父表:部門
CREATE TABLE dept (
deptno NUMBER(10) NOT NULL,
deptname VARCHAR2(30) NOT NULL,
CONSTRAINT pk_dept PRIMARY KEY (deptno)
);
-- 子表:員工
CREATE TABLE emp (
empno NUMBER(10) NOT NULL,
fname VARCHAR2(20),
lname VARCHAR2(20),
dept NUMBER(10), -- 外鍵欄位,允許 NULL
CONSTRAINT pk_emp PRIMARY KEY (empno)
);
-- 測試資料
INSERT INTO dept VALUES (1, '銷售部');
INSERT INTO dept VALUES (2, '財務部');
INSERT INTO emp VALUES (2, 'Mary', 'Song', 1);
INSERT INTO emp VALUES (3, 'Linda', 'Liu', 2);
INSERT INTO emp VALUES (4, 'Linlin', 'Zhang', 1);
COMMIT;
ALTER TABLE emp
ADD CONSTRAINT fk_emp_dept_cascade
FOREIGN KEY (dept) REFERENCES dept(deptno)
ON DELETE CASCADE;
DELETE FROM dept WHERE deptno = 1;
⚠ 級聯刪除會遞歸觸發:若 emp 又被其他表參考且也有 CASCADE,將連鎖刪除。需謹慎評估業務影響面。
-- 若原欄位有 NOT NULL,必須先移除
ALTER TABLE emp MODIFY (dept NULL);
ALTER TABLE emp DROP CONSTRAINT fk_emp_dept_cascade;
ALTER TABLE emp
ADD CONSTRAINT fk_emp_dept_setnull
FOREIGN KEY (dept) REFERENCES dept(deptno)
ON DELETE SET NULL;
INSERT INTO dept VALUES (1, '銷售部');
INSERT INTO emp VALUES (2, 'Mary', 'Song', 1);
INSERT INTO emp VALUES (4, 'Linlin', 'Zhang', 1);
COMMIT;
DELETE FROM dept WHERE deptno = 1;
dept 欄位自動設為 NULL,員工記錄保留。| 模式 | 語法 | 父表刪除時子表行為 | 子表欄位需求 | 典型場景 |
|---|---|---|---|---|
| 預設 (RESTRICT) | 無關鍵字 / ON DELETE RESTRICT | 阻止刪除,拋出 ORA-02292 | 無特殊要求 | 嚴格主從關係,禁止孤兒記錄(如訂單-明細) |
| 級聯刪除 | ON DELETE CASCADE | 自動刪除所有關聯子記錄 | 無特殊要求 | 弱關聯、臨時資料、快取表、日誌表 |
| 置空外鍵 | ON DELETE SET NULL | 子表外鍵欄位設為 NULL | 必須允許 NULL (無 NOT NULL) | 員工-部門、學生-班級等「隸屬關係可解除」場景 |
SET NULL 但子表欄位有 NOT NULL 約束。→ 移除 NOT NULL 或改用 CASCADE。SELECT constraint_name, delete_rule
FROM user_constraints
WHERE table_name = 'EMP' AND constraint_type = 'R';
DELETE_RULE 選擇理由。ON DELETE CASCADE 與 ON DELETE SET NULL 將級聯邏輯下推至資料庫核心,保證資料一致性且簡化應用代碼。選擇原則:「刪父必須刪子」→ CASCADE;「刪父子保留但解除關係」→ SET NULL(欄位可空);「刪父禁止」→ RESTRICT。掌握三種模式差異與約束條件,即可靈活應對各類主從表設計場景。