TRUNCATE vs DELETE:核心差異一覽
| 特性 | TRUNCATE TABLE | DELETE FROM |
| 語句類型 | DDL(隱式提交) | DML(需顯式 COMMIT) |
| 執行速度 | 極快(釋放資料頁,極少日誌) | 逐行刪除,產生大量 UNDO/REDO |
| 可回滾 | **不可回滾** | 可回滾 |
| 觸發器 | **不觸發** `BEFORE/AFTER DELETE` 行級觸發器 | 觸發所有相關觸發器 |
| 高水位線 (HWM) | **重置 HWM**,釋放空間 | 不重置 HWM,空間仍被佔用 |
| 外鍵約束 | 存在啟用的 FK 時**無法執行** | 可執行(受 FK 規則約束) |
語法與存儲選項
TRUNCATE TABLE table_name
[ { DROP | REUSE } STORAGE ]
[ CASCADE ]; -- 12c+ 支援級聯截斷參考表
- DROP STORAGE(預設): 釋放所有數據塊回表空間,HWM 歸零。
- REUSE STORAGE: 保留已分配的數據塊(HWM 不變),下次插入可直接複用,**適用於定期清空再重載的暫存表**,避免重複分配空間的開銷。
- CASCADE (12c+): 同時截斷透過外鍵引用本表的子表,需 FK 定義 `ON DELETE CASCADE`。
實戰範例
-- 建立測試表
CREATE TABLE tt (tid NUMBER(4));
INSERT INTO tt VALUES (1);
INSERT INTO tt VALUES (2);
INSERT INTO tt VALUES (3);
INSERT INTO tt VALUES (4);
INSERT INTO tt VALUES (5);
COMMIT;
-- 保留存儲空間截斷
TRUNCATE TABLE tt REUSE STORAGE;
SELECT * FROM tt; -- 無資料返回
-- 驗證 HWM 狀態
SELECT blocks, empty_blocks FROM user_segments WHERE segment_name = 'TT';
常見陷阱與避坑指南
- 誤以為可回滾: `TRUNCATE` 為 DDL,隱式提交前後交易,**無法 `ROLLBACK`**。生產環境執行前務必確認並備份。
- 外鍵阻擋: 若表被其他表 FK 引用且約束啟用,直接 `TRUNCATE` 會報 `ORA-02266`。解決方案:暫時 `DISABLE` FK、或使用 `DELETE`、或 12c+ `TRUNCATE ... CASCADE`。
- 觸發器失效: 依賴 `DELETE` 觸發器進行審計/同步的邏輯將失效,需改用 `FLASHBACK ARCHIVE` 或應用層記錄。
- 空間未釋放給 OS: `DROP STORAGE` 僅將空間歸還表空間,不會縮減資料檔大小。需配合 `ALTER TABLE ... MOVE` + `ALTER DATABASE DATAFILE ... RESIZE` 才能歸還作業系統。
- 權限要求: 需 `DROP ANY TABLE` 系統權限或為表擁有者,`DELETE` 權限不足以執行 `TRUNCATE`。
效能調優建議
- 大表清空(>100萬行)優先用 `TRUNCATE`,配合 `REUSE STORAGE` 避免重載時的空間分配等待。
- 分區表可使用 `TRUNCATE PARTITION` 僅清空特定分區,維護全域索引時加 `UPDATE GLOBAL INDEXES` 避免索引失效。
- 定期清空的暫存表/階段表,建議永久設定 `REUSE STORAGE` 並預分配足夠初始Extent。
掌握 `TRUNCATE` 的特性與限制,是 DBA 與開發人員高效管理資料生命週期的關鍵技能。