資料庫設計時為防誤刪常未啟用 ON DELETE CASCADE,但事後需求清理錯誤資料時必須級聯刪除。本文提供四種方案完整語法與適用場景比較。
CREATE TABLE fartab (far_id NUMBER(10) PRIMARY KEY, far_name VARCHAR2(10));
CREATE TABLE chiltab (chil_id NUMBER(10) PRIMARY KEY, far_id NUMBER(10) REFERENCES fartab(far_id));
CREATE TABLE gchiltab1 (gchil_id NUMBER(10) PRIMARY KEY, chil_id NUMBER(10) REFERENCES chiltab(chil_id));
CREATE TABLE chiltab (
chil_id NUMBER(10) PRIMARY KEY,
far_id NUMBER(10),
CONSTRAINT fk_chil FOREIGN KEY (far_id) REFERENCES fartab(far_id) ON DELETE CASCADE
);
優點:宣告式、效能最好、無額外程式碼。
缺點:需在建表時決定,事後修改較麻煩。
-- 1. 刪除原外鍵
ALTER TABLE gchiltab1 DROP CONSTRAINT fk_g1;
-- 2. 重建帶 CASCADE
ALTER TABLE gchiltab1 ADD (
CONSTRAINT fk_g1 FOREIGN KEY (chil_id) REFERENCES chiltab(chil_id) ON DELETE CASCADE
);
注意:
- 預設 VALIDATE 會檢查既有資料,大表可能耗時;若確定資料乾淨可加 NOVALIDATE 後再 VALIDATE。
- 參考欄位必須是 唯一/主鍵。
-- 父表 ordercombine,子表 vipform(參考非唯一鍵 formerid)
CREATE OR REPLACE TRIGGER ter_ov
BEFORE DELETE ON ordercombine
FOR EACH ROW
BEGIN
DELETE FROM vipform WHERE v_id = :OLD.formerid;
END;
/
測試:
DELETE FROM ordercombine WHERE formerid = '1'; → 子表關聯列自動刪除。
優點:邏輯可程式化、參考欄位無需唯一。
缺點:行級觸發器大量刪除時效能較差、維護成本高、易被遺忘。
DELETE FROM vipform WHERE v_id = '1';
DELETE FROM ordercombine WHERE formerid = '1';
優點:直觀、無隱性邏輯。
缺點:層級多、資料量大時極易遺漏、易出錯。
| 場景 | 推薦方案 | 備註 |
|---|---|---|
| 新建表、明確需級聯 | 方案一 | 標準做法 |
| 既有表、需啟用級聯、參考鍵為主鍵 | 方案二 | 注意 VALIDATE 鎖表 |
| 參考非唯一鍵、需複雜邏輯(如條件刪除、記錄日誌) | 方案三 | 加上 PRAGMA AUTONOMOUS_TRANSACTION 避免遞歸 |
| 僅 2 表、資料 < 1 萬筆、一次性清理 | 方案四 | 事後立即移除腳本 |
| 超大分區表、需秒級清理 | 交換分區 | 見「大表刪除重複資料」一文 |
若系統上線後不希望保留 CASCADE 風險,可於清理完成後再次 DROP CONSTRAINT ... ADD CONSTRAINT ... 移除 ON DELETE CASCADE,恢復保護模式。