這篇文章主要介紹了Oracle數據庫中的臨時表用法,但願對你們的學習和工做有所幫助。 html
在Oracle中,能夠建立如下兩種臨時表:
web(1) 會話特有的臨時表
(2) 事務特有的臨時表
所建的臨時表雖然是存在的,可是若是insert 一條記錄而後用別的鏈接登上去select,記錄是空的。
--ON COMMIT DELETE ROWS 說明臨時表是事務指定,每次提交後ORACLE將截斷表(刪除所有行)
--ON COMMIT PRESERVE ROWS 說明臨時表是會話指定,當中斷會話時ORACLE將截斷表。 sql
create or replace procedure pro_temp(v_col1 varchar2,v_col2 varchar2) as v_num number; begin select count(*) into v_num from user_tables where table_name=''T_TEMP''; --create temporary table if v_num<1 then execute immediate ''CREATE GLOBAL TEMPORARY TABLE T_TEMP ( COL1 VARCHAR2(10), COL2 VARCHAR2(10) ) ON COMMIT delete ROWS''; end if; --insert data execute immediate ''insert into t_temp values ('''''' v_col1 '''''','''''' v_col2 '''''')''; execute immediate ''select col1 from t_temp'' into v_num; dbms_output.put_line(v_num); execute immediate ''delete from t_temp''; commit; execute immediate ''drop table t_temp''; end pro_temp;
測試:
數據庫
臨時表只在當前鏈接內有效
臨時表不創建索引,因此若是數據量比較大或進行屢次查詢時,不推薦使用
數據處理比較複雜的時候時錶快,反之視圖快點
在僅僅查詢數據的時候建議用遊標: open cursor for ''sql clause'';
安全
==================性能優化
1、數據庫中的全部會話都可以訪問同一臨時表,但只有插入數據到臨時表中的會話才能看到它自己插入的數據。oracle
2、能夠把臨時表指定爲事務相關(默認)或者是會話相關:工具
3、若是臨時表中有記錄的話,是沒法刪除表的。即沒法drop table。sqlserver
4、雖然臨時表不產生 "REDO" ,但倒是要產生 "UNDO" 的post
記錄將留在此表中,直到會話斷開或經過DELETE或TRUNCATE從物理上刪除這些記錄。
CREATE GLOBAL TEMPORARY TABLE <TABLE_NAME> (<column specification> )
ON COMMIT PRESERVE ROWS;
當事務提交後,在事務之中插入的記錄不會被保留,自動刪除。
CREATE GLOBAL TEMPORARY TABLE <TABLE_NAME> (<column specification> )
ON COMMIT DELETE ROWS;
這裏的「GLOBAL」表示臨時表的定義,是全部會話都能看見的。創建臨時表只有 CREATE GLOBAL TEMPORARY TABLE,而沒有其它CREATE ****** TEMPORARY TABLE形式的命令。
想快速刪除此類臨時表,必須先truncate表中的數據,而後drop表結構。若是使用DELETE命令先刪除表中記錄的話,還沒法直接刪除表。只有等當前會話退出後,在其它會話或新的會話中刪除表結構。
使用DELTETE後DROP表報錯:
SQL> DELETE tmp_test;
8 rows deleted
SQL> commit;
Commit complete
SQL> drop table tmp_test;
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
這是由於用「ON COMMIT PRESERVE ROWS」子句時,會加行鎖(ROW-X).
TYPE=TO
TO Lock "Temporary Table Object Enqueue"
具體請看DOC ID:186854.1
用ON COMMIT DELETE ROWS 子句就不會有那麼多限制。COMMIT之後,記錄自動清除,能夠直接就刪除表。
臨時表在建立的時候,是不分配表空間的。當用戶使用臨時表存儲數據時,從該用戶默認的臨時表空間來分配存儲空間。
1、http://blog.itpub.net/post/10/8764
使用臨時表的sql優化案例二-臨時表的統計信息
2、http://www.itpub.net/178008.html&highlight=%C1%D9%CA%B1%B1%ED
拋磚引玉:三種主流數據庫中臨時表的使用.doc
MS SQLSERVER
SQL Server 支持臨時表。臨時表就是那些名稱以井號 (#) 開頭的表。若是當用戶斷開鏈接時沒有除去臨時表,SQL Server 將自動除去臨時表。臨時表不存儲在當前數據庫內,而是存儲在系統數據庫 tempdb 內。
臨時表有兩種類型:
本地臨時表:本地臨時表的名稱以單個數字符號 (#) 打頭;它們僅對當前的用戶鏈接是可見的;當用戶從 Microsoft SQL Server 2000 實例斷開鏈接時被刪除。
全局臨時表:全局臨時表的名稱以數學符號 (##) 打頭,建立後對任何用戶都是可見的。若是在建立全局臨時表的鏈接斷開前沒有顯式地除去這些表,那麼只要全部其它任務中止引用它們,這些表即被除去。當建立全局臨時表的鏈接斷開後,新的任務不能再引用它們。當前的語句一執行完,任務與表之間的關聯即被除去;所以一般狀況下,只要建立全局臨時表的鏈接斷開,全局臨時表即被除去。
例如,若是建立名爲 employees 的表,則任何人只要在數據庫中有使用該表的安全權限就可使用該表,除非它已刪除。若是建立名爲 #employees 的本地臨時表,只有您能對該表執行操做且在斷開鏈接時該表刪除。若是建立名爲 ##employees 的全局臨時表,數據表中的任何用戶都可對該表執行操做。若是該表在您建立後沒有其餘用戶使用,則當您斷開鏈接時該表刪除。若是該表在您建立後有其餘用戶使用,則 SQL Server在全部用戶斷開鏈接後刪除該表。
如今,臨時表的許多傳統用途可由具備 table 數據類型的變量替換。
ORACLE
Oracle支持臨時表。臨時表用來保存事務或會話期間的中間結果。在臨時表中保存的數據只有對當前會話是可見的,任何會話都不能看到其餘會話的數據,即便在當前會話COMMIT數據之後也是不可見的。多用戶並行不是問題,一個會話歷來不阻塞另外一個會話使用臨時表。即便鎖定臨時表,一個會話也不會阻塞其餘會話使用臨時表。臨時表比正常表產生的REDO少得多,然而,因爲臨時表必須產生包含數據的UNDO信息,因此會產生必定數量的REDO日誌。
臨時表將從用戶臨時表空間的的目前日誌中分配空間,或者若是從有定義權的程序中訪問,將使用程序全部者的臨時表空間。全局臨時表實際上只是表自己的模板。建立臨時表的行爲不包括存儲空間的分配,也不包括INITIAL的分配。所以,在運行時當一個會話首先將數據放到臨時表中時,這時將建立這個會話的臨時段。因爲每一個會話獲取本身的臨時段,每一個用戶可能在不一樣的表空間中爲臨時表分配空間。USER1的default臨時表空間爲TEMP1,他的臨時表將從TEMP1中分配空間,USER2的default臨時表空間爲TEMP2,他的臨時表將從TEMP2中分配空間。
臨時表在每一個數據庫中只需建立一次,沒必要在每一個存儲過程當中建立。臨時表老是存在的,除非手動的刪除他。臨時表做爲對象存在數據字典中,而且老是保持爲空,直到有會話在其中放入數據。Oracle容許建立基於臨時表的視圖和存儲過程。
臨時表能夠是以會話爲基礎的,也能夠是以事務爲基礎的。ON COMMIT PRESERVE ROWS子句使臨時表成爲基於會話的模式。行將留在此表中,直到會話斷開或經過DELETE或TRUNCATE從物理上刪除這些行。ON COMMIT DELETE ROWS子句使臨時表成爲基於事務的模式。當會話提交後,行消失。這個臨時表的自動清除過程不會有額外的開銷。
在oracle中,應用程序須要的臨時表應該在程序安裝時建立,而不是在程序運行時建立。(這是與ms sqlserver或sybase的使用的不一樣)
在任何數據庫中,臨時表的一個缺點是:事實上優化器在臨時表中沒有真正的統計功能。然而,在oracle中,一系列較好的統計猜想能夠經過DBMS_STATS包在臨時表中設置。
DB2
可以使用 DECLARE GLOBAL TEMPORARY TABLE 語句來定義臨時表。DB2的臨時表是基於會話的,且在會話之間是隔離的。當會話結束時,臨時表的數據被刪除,臨時表被隱式卸下。對臨時表的定義不會在SYSCAT.TABLES中出現
下面是定義臨時表的一個示例:
DECLARE GLOBAL TEMPORARY TABLE gbl_temp
LIKE empltabl
ON COMMIT DELETE ROWS
NOT LOGGED
IN usr_tbsp
此語句建立一個名爲 gbl_temp 的用戶臨時表。定義此用戶臨時表 所使用的列的名稱和說明與 empltabl 的列的名稱和說明徹底相同。隱式定義 只包括列名、數據類型、可爲空特性和列缺省值屬性。未定義全部其餘列屬性,包括惟一約束、外部關鍵字約束、觸發器和索引。執行 COMMIT 操做時, 若未對該表打開 WITH HOLD 遊標,則該表中的全部數據都被刪除。不記錄 對用戶臨時表所做的更改。用戶臨時表被放在指定的用戶臨時表空間中。此表空間必須存在,不然此表的聲明將失敗。
戶定義臨時表不支持:
LOB 類型的列(或基於 LOB 的單值類型列)
用戶定義類型列
LONG VARCHAR 列
DATALINK 列
End of document.
臨時表是複雜SQL性能優化中常見手段,總結一下。
會話級的臨時表
【語法】
【特色】
臨時表數據自動清空後,可是臨時表的結構以及元數據還存儲在用戶的數據字典中。表的定義對全部的會話可見。
臨時表不須要DML鎖。 www.2cto.com
能夠索引臨時表和在臨時表基礎上創建視圖。
在臨時表上的索引也是臨時的,也是隻對當前會話或者事務有效。
臨時表能夠擁有觸發器。
能夠用export和import工具導入導出臨時表的定義,可是不能導出數據。
【適用場合】
當某一個SQL語句多表關聯,而且和一些小表關聯。能夠採用將大表進行分拆而且獲得比較小的結果集合存放在臨時表中。
程序執行過程當中屢次使用的臨時數據,這些數據在整個程序的會話過程當中都須要用的等等。
【清除時點】
當某一個SESSION退出以後自動清除數據(表結構保留)
【不足】
不支持lob對象,這也許是設計者基於運行效率的考慮,但實際應用中確實須要此功能時就沒法使用臨時表了。
不支持主外鍵關係。
例子:
CREATE GLOBAL TEMPORARY TABLE my_temporary (birthdate DATE, enddate DATE, name CHAR(20)) ON COMMIT PRESERVE ROWS;
事務級的臨時表
【語法】
Create Global Temporary Table Table_Name
(the aggregation SQL statement) On Commit Delete Rows;
【清除時點】 當執行COMMIT以後自動清除數據(表結構保留)
其餘方面與會話級的臨時表相同,再也不列出。
準確的說with語句不叫臨時表,但它與臨時表使用概念上很是接近,一樣列出。
【語法】
【特色】
附着於一個SQL 語句,也只對一個SQL語句產生做用。
能夠同時生成幾張臨時表。
生存期極短,易於管理。
【適用場合】
Global Temporary 的適用場合都適用,只是針對一個SQL的場合
特別方便融入常量或集合運算結果,有簡化SQL的做用。
【清除時點】
查詢完成後當即清除(數據及表結構)。
例子:
WITH sum_sales AS ( select /*+ materialize */ sum(quantity) all_sales from stores ), number_stores AS ( select /*+ materialize */ count(*) nbr_stores from stores ), sales_by_store AS ( select /*+ materialize */ store_name, sum(quantity) store_sales from store natural join sales ) SELECT store_name FROM store, sum_sales, number_stores, sales_by_store where store_sales > (all_sales / nbr_stores)
(注:使用/*+ materialize */讓Oracle基於cost-based(基於成本)的優化策略生成臨時表。 )