一、问题描述
通常我们在删除临时表时会遇到的ORA-14452报错问题,首先我们先了解一下什么是临时表(temporary table),顾名思义就是临时使用,使用完自动清理。按要清理条件分为两种:1.事务 2.会话。而且临时表中存入的数据对当前会话是私有的,每个会话只能读取使用自己的数据。
二、官方给出报错信息
ORACLE 给出报错代码信息:
小结:会话一结束事务后,会话二才能够删除全局临时表。也还可以通过查询哪个用户持有sam_tmp表锁,将会话kill掉后再drop table 即可。下面是会话级别的temporary table 我们需要将会话kill掉才能够删除全局临时表。
-
[oracle@test ~]$ oerr ora 14452
-
14452, 00000, "attempt to create, alter or drop an index on temporary table already in use"
-
// *Cause: An attempt was made to create, alter or drop an index on temporary
-
// table which is already in use.
-
// *Action: All the sessions using the session-specific temporary table have
-
// to truncate table and all the transactions using transaction
- // specific temporary table have to end their transactions.
三、实验
(1)事务级临时表
会话一:
1.创建基于事务的临时表
-
SCOTT@OCM11G >create global temporary table sam_tmp (name varchar2(10)) on commit delete rows;
-
- Table created.
2.插入测试数据
-
SCOTT@OCM11G >insert into sam_tmp values ('sam');
-
- 1 row created.
3.检查数据
-
SCOTT@OCM11G >select * from sam_tmp;
-
-
NAME
-
----------
- sam
会话二:
1.删除全局临时表时报错ORA-14452
-
SCOTT@OCM11G >drop table sam_tmp;
-
drop table sam_tmp
-
*
-
ERROR at line 1:
-
ORA-14452: attempt to create, alter or drop an index on temporary table already
- in use
(2)会话级临时表
会话一:
1.创建基于会话的临时表
-
SCOTT@OCM11G >create global temporary table sam_tmp1 (name varchar2(10)) ON COMMIT PRESERVE ROWS;
-
- Table created.
2.插入测试数据
-
SCOTT@OCM11G >insert into sam_tmp1 values ('suzzy');
-
- 1 row created.
3.检查数据
-
SCOTT@OCM11G >select * from sam_tmp1;
-
-
NAME
-
----------
- suzzy
4.提交数据
-
SCOTT@OCM11G >commit;
-
- Commit complete.
会话二:
1.删除全局临时表时报错ORA-14452
-
SCOTT@OCM11G >drop table sam_tmp1;
-
drop table sam_tmp1
-
*
-
ERROR at line 1:
-
ORA-14452: attempt to create, alter or drop an index on temporary table already
- in use
2.会话三中将sid=237 serial#=29 的会话kill后,可以成功drop table。 还有一种情况,可以drop table成功,那就是会话一将表中数据truncate,注意delete 加 commit; 是不成的。 必须truncate 。 这个小例子就留给各位朋友自己测试喽。
-
SCOTT@OCM11G >drop table sam_tmp1;
-
- Table dropped.
会话三:
1.查询出谁锁住了对象 SAM_TMP1
-
SYS@OCM11G >SELECT SID, SERIAL# FROM V$SESSION V WHERE sid in (select sid from v$lock l, dba_objects o WHERE L.ID1 = O.OBJECT_ID AND O.OBJECT_NAME =UPPER('SAM_TMP1'));
-
-
SID SERIAL#
-
---------- ----------
- 237 29
2.KILL锁住对象SAM_TMP1临时表的连接
-
SYS@OCM11G >ALTER SYSTEM KILL SESSION '237, 29';
-
- System altered.
小结:会话一结束会话或者truncate临时表后,才可以drop 这张临时表。 当然让连接的用户自己断开连接也不太可能,这时DBA可以采用alter system kill session 'sid, serial#’ ; 来kill 锁住临时表的会话。
四、总结
临时表这个东东,看来只有DBA们会用,其实开发人员也应该多多学习一下它,会解决开发很多问题。自己去用程序控制临时表,费时费力,不如直接使用ORACLE提供的,很高效,安全。再回顾一下,temporary table : There are two mode , 1. for transaction 2 for session . Let’s study more oracle technology include dba and developer. Where there is a will, there is a way.