Oracle 默認外鍵行為為「限制刪除」(RESTRICT),即父表記錄被子表引用時禁止刪除。實際業務中常需級聯刪除或置空。本文通過完整構建測試場景,深度對比 ON DELETE CASCADE 與 ON DELETE SET NULL 的行為差異、適用場景及注意事項。
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), -- 故意不加 NOT NULL,為 SET 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;
| 表 | 操作前 | 操作後 | 說明 |
|---|---|---|---|
| DEPT | 2 行 (1, 2) | 1 行 (2) | 部門 1 被刪除 |
| EMP | 3 行 | 1 行 (Linda, 部門 2) | Mary、Linlin 關聯部門 1,**同步刪除** |
-- 恢復數據
INSERT INTO dept VALUES (1, '銷售部');
INSERT INTO emp VALUES (2, 'Mary', 'Song', 1);
INSERT INTO emp VALUES (4, 'Linlin', 'Zhang', 1);
COMMIT;
-- 刪除舊約束,創建新約束
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;
DELETE FROM dept WHERE deptno = 1;
| 表 | 操作前 | 操作後 | 說明 |
|---|---|---|---|
| DEPT | 2 行 (1, 2) | 1 行 (2) | 部門 1 被刪除 |
| EMP | 3 行 | 3 行 | Mary、Linlin 的 dept 列變為 NULL,行保留 |
-- 若 emp.dept 定義了 NOT NULL
CREATE TABLE emp (
...
dept NUMBER(10) NOT NULL, -- 這裡加了 NOT NULL
...
);
-- 創建 ON DELETE SET NULL 會報錯
-- ORA-02299: cannot validate (FK) - null values found
-- 或刪除父記錄時:ORA-01407: cannot update ("SCOTT"."EMP"."DEPT") to NULL
| 策略 | 語法 | 父刪除時子表行為 | 典型場景 | 風險 |
|---|---|---|---|---|
| 限制 (默認) | 無需指定 | 報錯阻止刪除 | 嚴格主從、需人工確認 | 業務阻塞 |
| 級聯刪除 | ON DELETE CASCADE | 子行同步刪除 | 強綁定、明細無獨立價值 | 誤刪連鎖、性能衝擊 |
| 置空 | ON DELETE SET NULL | 外鍵列置 NULL,行保留 | 弱關聯、需保留子記錄 | NULL 語義歧義、查詢需處理 |
Oracle 不支持 ON UPDATE CASCADE/SET NULL。主鍵更新需:
或使用觸發器實現 (不推薦,複雜且易錯)。
ON DELETE 策略外鍵刪除策略是資料完整性與業務靈活性的平衡點。ON DELETE CASCADE 提供強一致性但風險連鎖,ON DELETE SET NULL 保留歷史但引入 NULL 處理複雜度。深業務建模、嚴測試驗證、文檔先行,方能用好這把雙刃劍。