Oracle臨時表是一類特殊的表,Oracle臨時表(Temporary table)用於保存事務或會話期間的中間結果集。下面就為您詳細介紹Oracle臨時表相關的知識,供您參考。
臨時表中保存的數據只對當前會話可見,所有會話都看不到其他會話的數據;臨時表比常規表生成的redo少得多。不過,由於臨時表必須為其中包含的數據生成undo信息, 所以也會生成一定的redo。 UPDATE和DELETE會生成最多的undo; INSERT和SELECT生成的undo最少。
對於Oracle臨時表,運行時當一個會話第一次在臨時表中放入數據時,才會為該會話創建一個臨時段。由於每個會話會得到其自己的臨時段(而不是一個現有段的一個區段),每個用戶可能在不同的表空間為其臨時表分配空間。
Oracle臨時表與其他關系數據庫中的臨時表類似,這樣區別只是:Oracle臨時表是“靜態”定義的。每個數據庫只創建一次臨時表,而不是為數據庫中的每個存儲過程都創建一次。在Oracle中,臨時表一定存在,它們作為對象放在數據字典中,但是在會話向臨時表中放入數據之前,臨時表看上去總是空。由於臨時表是靜態定義的,所以你能創建引用臨時表的視圖,還可以創建存儲過程使用靜態SQL來引用臨時表,等等。臨時表可以是基於會話的(臨時表中的數據可以跨提交存在,即提交之前仍然存在,但是斷開連接後再連接後再連接時數據就沒有了),也可以是基於事務的(提交之後數據就消失)。下面這個例子顯示了這兩種不同的臨時表。我使用SCOTT.EMP表作為一個模板:
- ops$tkyte@ORA10G> create global temporary table temp_table_session
- 2 on commit preserve rows
- 3 as
- 4 select * from scott.emp where 1=0
- 5 /
- Table created.
ON COMMIT PRESERVE ROWS 子句使得這是一個基於會話的臨時表。在我的會話斷開連接之前,或者我通過一個DELETE或TRUNCATE物理地刪除行之前,這些行會一直存在於這個臨時表中。
- ops$tkyte@ORA10G> create global temporary table temp_table_transaction
- 2 on commit delete rows
- 3 as
- 4 select * from scott.emp where 1=0
- 5 /
- Table created.
ON COMMIT DELETE ROWS 子句使得這是一個基於事務的臨時表。我的會話提交時,臨時表中的行就不見了。只需把分配給這個表的臨時區段交回,這些行就會消失,在臨時表的自動清除過程中不存在開銷。
如果你曾在SQL Server和/或 Sybase中用過臨時表,現在所要考慮的主要問題是:不應該執行SELECT X, Y, Z INTO #TEMP FROM SOME_TABLE來動態創建和填充一個臨時表,而應該:
l 將所有全局臨時表只創建一次,作為應用安裝的一部分,就像是創建永久表一樣。
l 在你的過程中,只需執行INSERT INTO TEMP(X, Y, Z) SELECT X, Y, Z FROM SOME_TABLE。
歸根結底,這裡的目標是:不要在運行時在你的存儲過程中創建表。這不是Oracle 中使用臨時表的正確做法。DDL是一種代價昂貴的操作:你要全力避免在運行時執行這種操作。一個應用的臨時表應該在應用安裝期間創建,絕對不要在運行時創建。
Oracle臨時表可以有永久表的許多屬性。它們可以有觸發器、檢查約束、索引等。但永久表的某些特性在臨時表中並不支持,這包括:
l 不能有引用完整性約束。臨時表不能作為外鍵的目標,也不能在臨時表中定義外鍵。
l 不能有 NESTED TABLE類型的列。 在 Oracle 9i及以前版本中, VARRAY類型的列也不允許;不過Oracle 10g中去掉了這個限制。
l 不能是 IOT。
l 不能在任何類型的聚簇中。
l 不能分區。
l 不能通過ANALYZE表命令生成統計信息。
在所有數據庫中,臨時表的缺點之一是優化器不能正常地得到臨時表的真實統計。