错误码:-2068
错误内容:在参数ENABLE_TMP_TAB_ROLLBACK为0或STANDBY模式下,不支持对包含唯一索引的临时表进行增删改操作
1、在主备环境下,构造测试用例
--创建表
create table t1(id number,name varchar2(20),constraint PK_T1_ID not cluster primary key (ID));
create global temporary table TMP_T1(ID number,NAME varchar2(128),constraint PK_TMPT1_ID not cluster primary key (ID));
--插入数据
insert into t1 values (1,'TONY');
insert into t1 values (2,'STEVE');
commit;
--创建包,其中函数实现查询返回结果,存储过程实现将数据插入临时表进行处理
create or replace package pkg_test_1 as
function f_getname(vid number) return varchar2;
procedure p_inst(vid number);
end;
/
create or replace package body pkg_test_1 as
function f_getname(vid number) return varchar2
as
res_name varchar2(20);
begin
select name into res_name from T1 where id=vid;
return res_name;
end;
procedure p_inst(vid number)
as
begin
insert into TMP_T1 select * from t1 where id=vid;
end;
end;
/
2、当备库执行调用包里的函数时会出现-2068报错
[执行语句1]:
select pkg_test_1.f_getname(1) from dual;
执行失败(语句1)
-3325: 第14 行附近出现错误[-2068]:在参数ENABLE_TMP_TAB_ROLLBACK为0或STANDBY模式下,不支持对包含唯一索引的临时表进行增删改操作
包里存在两个方法,函数为查询操作,存储过程为DML操作,备库只读正常应该允许执行查询,而问题场景中即使没有直接调用包里的存储过程,结果还是会出现报错。
1、DM对于PL/SQL代码块会先获取所有语句的计划,在调用包时存储过程中的DML语句也需要进行解析,因此在备库模式下执行查询操作也会报错;
2、ENABLE_TMP_TAB_ROLLBACK默认为1,表示临时表操作是否生成回滚记录,0:不生成;1:生成。置为0时,有三项限制:
一是临时表的 DML 操作无法回滚;
二是不允许对包含唯一索引的临时表进行增删改操作;
三是不允许对临时表创建唯一索引、主键约束和唯一约束;
因此当ENABLE_TMP_TAB_ROLLBACK=0的情况下,无论主库还是备库都会出现相关报错。
1、可以将存储过程中的语句改写为动态执行,可以避免存储过程中的语句被提前解析;
procedure p_inst(vid number)
as
begin
execute immediate 'insert into TMP_T1 select * from t1 where id='||vid;
--insert into TMP_T1 select * from t1 where id=vid;
end;
2、当临时表中不存在主键或唯一索引的情况下,也可以避免-2068报错,但删除唯一约束可能会改变应用程序的业务逻辑;
文章
阅读量
获赞