1.臨時表分爲:
會話級臨時表:臨時表中的數據只在會話生命週期之中存在,當用戶退出會話結束的時候,Oracle自動清除臨時表中數據。
事務級臨時表:臨時表中的數據只在事務生命週期中存在。當一個事務結束(commit or rollback),Oracle自動清除臨時表中數據。
2.創建:
會話級:CREATE GOLBAL TEMPORARY TABLE TEMP_TBL1 (RT_ID VARCHAR2(20),PAT_ID VARCHAR2(20)) ON COMMIT PRESERVE ROWS ;
事務級:CREATE GOLBAL TEMPORARY TABLE TEMP_TBL2 (RT_ID VARCHAR2(20),PAT_ID VARCHAR2(20)) ON COMMIT DELETE ROWS ;
(紅色字體爲固定寫法,黑色字體爲自定義)
3.區別:
事務級的在sql中只要執行commit命令,則臨時表中的數據就被清空。
會話級的在執行完後,即當前訪問結束後,臨時表中的數據就被清空,如c#調用完存儲過程後,就會被清空。
4.相同點:
1. 臨時表中的數據只對當前Session有效,每個Session都有自己的臨時數據,並且不能訪問其它Session的臨時表中的數據。即:多個客戶端同時訪問服務器上的同一個臨時表時,並不能看到別的用戶的數據,也無法對其進行操作,但表是存在的。所以如果要創建臨時表,應先執行
SELECT COUNT(*) INTO TEMP_TBL_COUNT FROM USER_TABLES T WHERE T.TABLE_NAME = 'TEMP_TBL';
(TEMP_TBL_COUNT 爲number型的變量,保存檢索出來的個數;TEMP_TBL爲創建的臨時表的名字。)
只有當TEMP_TBL_COUNT =0的時候才創建臨時表。
2. 當多個人同時使用的時候是無法刪除臨時表的,雖然多個用戶彼此看不到也無法操作對方的數據,但表還是同一個,只是各自有各自的session。如果採用實體表的話,要防止多個人同時操作同一個表,那在創建實體表的時候應多加一個session_id的字段,區別各個用戶。
3. EXECUTE IMMEDIATE:執行命令,因爲在存儲過程中無法直接執行,可以用該命令加上’要執行的命令‘來實現select,insert,delete等操作。如創建臨時表
EXECUTE IMMEDIATE ' CREATE GOLBAL TEMPORARY TABLE TEMP_TBL1 (RT_ID VARCHAR2(20),PAT_ID VARCHAR2(20)) ON COMMIT PRESERVE ROWSROWS ‘ ;
COMMIT:提交命令,當用EXECUTE IMMEDIATE執行完後,對於insert和delete操作,要記得commit(事務級的臨時表不需要,因爲commit會清空其數據)。同時commit會導致事務級的臨時表的數據清空。
4. 直接在在plsql中查看臨時表是看不到數據的,需要用遊標將其取出則可以看到。如:
PROCEDURE TEMP_TBL_TEST(STR IN VARCHAR) IS
CUR_A_CURSOR REF_CURSOR;
V_C_RT_ID VARCHAR(20);
V_C_PAT_ID VARCHAR(20);
BEGIN
OPEN CUR_A_CURSOR FOR 'SELECT * FROM TONG_TEMP_TBL'; //TONG_TEMP_TBL爲已經創建好的臨時表
LOOP
FETCH CUR_A_CURSOR
INTO V_C_RT_ID, V_C_PAT_ID;
EXIT WHEN CUR_A_CURSOR%NOTFOUND;
END LOOP;
END TEMP_TBL_TEST;
5. 舉例:
// 查找臨時表是否已經存在
SELECT COUNT(*)
INTO TEMP_TBL_COUNT
FROM USER_TABLES T
WHERE T.TABLE_NAME = 'TONG_TEMP_TBL2';
//如果臨時表不存在則創建事務級的臨時表
IF TEMP_TBL_COUNT = 0 THEN
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE TONG_TEMP_TBL2(C_RT_ID VARCHAR2(20), C_PAT_ID VARCHAR2(20)) ON COMMIT DELETE ROWS';
ELSE
//如果臨時表存在則清空其數據,在這也可以利用執行commit;命令來清空。
EXECUTE IMMEDIATE 'truncate TABLE TONG_TEMP_TBL2';
END IF;
COMMIT;
//往臨時表中插入數據,在執行完後別忘了執行commit(會話級的臨時表需要);
EXECUTE IMMEDIATE 'INSERT INTO TONG_TEMP_TBL2 ( ' ||
'SELECT TONG_TEMP_TBL.C_RT_ID,
TONG_TEMP_TBL.C_PAT_ID
FROM TONG_TEMP_TBL WHERE NOT EXISTS( SELECT 1 FROM( ' ||
C_FREE_WORD1 ||
') T2 WHERE T2.C_RT_ID = TONG_TEMP_TBL.C_RT_ID AND T2.C_PAT_ID = TONG_TEMP_TBL.C_PAT_ID))';