需要使用Oracle的临时表,向其中插入记录,用完后再删除。但是后来发现临时表的删除总是失败,返回错误:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
这个错误是Oracle的临时表设计原理造成。在Oracle中,临时表是同session绑定在一起的,准确的说,是表中的数据及相关的事物是同 session绑定的,这个绑定是从session首次向表中插入数据开始的。不同的session可以向同一个临时表中插入记录,提交事务,但是即使在 提交事务之后,不同的session从同一个临时表中选出的数据也是不一样的——一个session只能选出自己插入的数据。
临时表在会话结束后会被truncate,当然,truncate也不会影响其它的会话。这个操作解除了临时表同当前会话之间的关系,只有这样,才能使用drop语句删除临时表。不过如果此时还有其它会话在使用这个临时表,那么drop操作自然也会失败。
上面所说的情况是针对使用 CREATE GLOBAL TEMPORARY TABLE XXXX (......) on commit preserve rows 语句创建的临时表。
--------------------------------------------------------------------------------------------------------------------------------
1、数据库中的所有会话均可以访问同一临时表,但只有插入数据到临时表中的会话才能看到它本身插入的数据。
2、可以把临时表指定为事务相关(默认)或者是会话相关:
3、如果临时表中有记录的话,是无法删除表的。即无法drop table。
4、虽然临时表不产生 "REDO" ,但却是要产生 "UNDO" 的
-----------------------------------------------------------------------------------------------------------------------------------------
1、删除会话特有的临时表
想快速删除此类临时表,必须先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
2、删除事务特有的临时表
用ON COMMIT DELETE ROWS 子句就不会有那么多限制。COMMIT以后,记录自动清除,可以直接就删除表。
临时表的表空间的分配
临时表在创建的时候,是不分配表空间的。当用户使用临时表存储数据时,从该用户默认的临时表空间来分配存储空间。