場景:事務中向全局臨時表 tmp1 插入數據 → 循環創建另一臨時表 tmp2(DDL 操作) → 查詢 tmp1 發現數據消失。
原建表語句:
CREATE GLOBAL TEMPORARY TABLE crm_t_11961 ( cust_id VARCHAR(30), cust_name VARCHAR(100) ) ON COMMIT DELETE ROWS;
DDL 隱式提交:Oracle 中任何 DDL 語句(CREATE TABLE、DROP、TRUNCATE、ALTER 等)執行前會自動提交當前事務。
ON COMMIT DELETE ROWS:臨時表定義為事務級,每次提交後 Oracle 自動截斷表(刪除所有行)。
因此:創建 tmp2 觸發隱式提交 → 事務結束 → tmp1 數據被清空。
CREATE GLOBAL TEMPORARY TABLE crm_t_11961 ( cust_id VARCHAR(30), cust_name VARCHAR(100) ) ON COMMIT PRESERVE ROWS;
ON COMMIT PRESERVE ROWS:臨時表為會話級,數據在會話結斷(斷開連接)時才清空,跨事務保留。
| 特性 | ON COMMIT DELETE ROWS (事務級) | ON COMMIT PRESERVE ROWS (會話級) |
|---|---|---|
| 數據生命週期 | 當前事務 | 當前會話 |
| 提交/回滾後 | 數據清空 | 數據保留 |
| DDL 執行後 | 數據清空(隱式提交) | 數據保留 |
| 適用場景 | 單事務內中間結果、ETL 階段表 | 跨多事務/請求的暫存、報表中間表 |
| 並發隔離 | 各事務獨立 | 各會話獨立 |
EXECUTE IMMEDIATE 在獨立事務中執行 DDL(PRAGMA AUTONOMOUS_TRANSACTION),但需謹慎設計。DBMS_SESSION 上下文變量傳遞中間結果。DBMS_STATS.GATHER_TABLE_STATS(僅對當前會話有效)或動態採樣 /*+ DYNAMIC_SAMPLING(4) */。-- 會話級測試 CREATE GLOBAL TEMPORARY TABLE gtt_session (id NUMBER) ON COMMIT PRESERVE ROWS; INSERT INTO gtt_session VALUES (1); COMMIT; SELECT * FROM gtt_session; -- 返回 1 行 -- 事務級測試 CREATE GLOBAL TEMPORARY TABLE gtt_txn (id NUMBER) ON COMMIT DELETE ROWS; INSERT INTO gtt_txn VALUES (1); COMMIT; SELECT * FROM gtt_txn; -- 返回 0 行