在刪除臨時表時遇到了ORA-14452錯誤:ORA-14452: attempt to create , alert or drop an index on temporary table already in use。第一次碰到這種情況,問題解決過后,為了加深理解,特意參考網上資料,做了下面實驗重現錯誤出現的場景,以及應該如何解決.
會話級臨時表
由於實驗需要兩個或多個會話配合,所以使用SET SQLPROMPT來標識會話,如下所示,SESSION 1與SESSION 2:
Step 1:在會話1中創建了會話級的臨時表TMP_TEST
1 SQL> SET SQLPROMPT "SESSION 1 >" 2 SESSION 1 >CREATE GLOBAL TEMPORARY TABLE TMP_TEST 3 2 ( NAME VARCHAR2(12) ) ON COMMIT PRESERVE ROWS; 4 5 Table created. 6 7 SESSION 1 >INSERT INTO TMP_TEST VALUES('Kerry'); 8 9 1 row created. 10 11 SESSION 1 >COMMIT; 12 13 Commit complete. 14 15 SESSION 1 >SELECT * FROM TMP_TEST; 16 17 NAME 18 ------------ 19 Kerry
Step 2:打開另外一個會話2,在這個會話里面操作臨時表TMP_TEST,插入數據。
1 SQL> SET SQLPROMPT "SESSION 2 >" 2 SESSION 2 >SELECT * FROM TMP_TEST; 3 4 no rows selected 5 6 SESSION 2 >INSERT INTO TMP_TEST VALUES('Jimmy'); 7 8 1 row created. 9 10 SESSION 2 >SELECT * FROM TMP_TEST; 11 12 NAME 13 ------------ 14 Jimmy
Step 3: 在會話1中刪除臨時表時,就會出現ORA-14452錯誤。
1 SESSION 1 >TRUNCATE TABLE TMP_TEST; 2 3 Table truncated. 4 5 SESSION 1 >DROP TABLE TMP_TEST; 6 DROP TABLE TMP_TEST 7 * 8 ERROR at line 1: 9 ORA-14452: attempt to create, alter or drop an index on temporary table already in use
Step 4: 如果在會話2中先清空數據,然后去會話1中刪除表則可順利完成
1 SESSION 2 >TRUNCATE TABLE TMP_TEST; 2 3 Table truncated. 4 5 6 SESSION 1 >DROP TABLE TMP_TEST; 7 8 Table dropped.
事務級臨時表
Step 1: 在會話1中創建事務級全局臨時表。
1 SESSION 1 >CREATE GLOBAL TEMPORARY TABLE TMP_TEST 2 2 ( NAME VARCHAR2(12) ) ON COMMIT DELETE ROWS; 3 4 Table created. 5 6 SESSION 1 >INSERT INTO TMP_TEST 7 2 VALUES('Kerry'); 8 9 1 row created. 10 11 SESSION 1 >SELECT * FROM TMP_TEST; 12 13 NAME 14 ------------ 15 Kerry 16 17 SESSION 1 >COMMIT;
Step 2:在會話2中插入一條記錄。
1 SESSION 2 >INSERT INTO TMP_TEST VALUES('Jimmy'); 2 3 1 row created. 4 5 SESSION 2 >SELECT * FROM TMP_TEST; 6 7 NAME 8 ------------ 9 Jimmy
Step 3: 在會話3中刪除全局臨時表時就會報錯
1 SESSION 1 >SELECT * FROM TMP_TEST; 2 3 no rows selected 4 5 SESSION 1 >TRUNCATE TABLE TMP_TEST; 6 7 Table truncated. 8 9 SESSION 1 >DROP TABLE TMP_TEST; 10 DROP TABLE TMP_TEST 11 * 12 ERROR at line 1: 13 ORA-14452: attempt to create, alter or drop an index on temporary table already in use
Step 4: 在會話2中提交后,即可在會話1中刪除全局臨時表。
SESSION 2 >COMMIT;
Commit complete.
總結:不管事務級還是會話級的臨時表,都需要所有會話解除綁定,才能DROP,解除綁定的辦法就是清空每個會話的數據.清空數據的辦法:事務級別的臨時表:COMMIT/TRUNCATE TABLE;會話級的臨時表:TRUNCATE TABLE ;但是很多時候,如果出現了這種錯誤,但是我們不知道是那個用戶的那個會話沒有解除綁定,那么此時要如何解決呢?你可以用下面SQL語句來查詢那個會話沒有解除綁定,然后殺掉會話進程。
1 SELECT SID, SERIAL# FROM V$SESSION V 2 WHERE SID IN (SELECT SID FROM V$LOCK L, DBA_OBJECTS O 3 WHERE L.ID1 = O.OBJECT_ID AND O.OBJECT_NAME =UPPER('TMP_TEST') ); 4 5 ALTER SYSTEM KILL SESSION 'SID, SERIAL#';
或者你使用下面步驟一步一步的去定位那個會話沒有解除綁定。
Step 1、先從DBA_OBJECTS/ALL_OBJECTS /USER_OBJECTS中查詢到該表的OBJECT_ID:
SELECT OBJECT_ID FROM USER_OBJECTS WHERE OBJECT_NAME='TMP_TEST'
Step 2、根據查到的OBJECT_ID知道使用該表的SESSION:
SELECT * FROM V$LOCK WHERE ID1=&OBJECT_ID;
Step 3、在從v$session視圖中查到該session的SID和SERIAL#:
SELECT * FROM V$SESSION WHERE SID=&SID;
Step 4、殺掉這些進程:
ALTER SYSTEM KILL SESSION 'SID, SERIAL#';
參考資料:
http://blog.itpub.net/70612/viewspace-1034301/