在过程A里drop掉某个table,再create起来,而过程B恰好调用该table就会出现这种错误。虽然当过程B调用的这个table的时候,过程A已经帮它重建了,但不知道为什么还是会出错。而且在出错的时候,如果过程A没用exception捕获的话,过程A会试着重新运行一遍自己,如果还出错,就停止。
我做了两个小程序给大家演示看看:
大家需要预先建两个table,log和log1(log1是事后的主要日志文件)
create table log (a varchar2(500));
create table log1 (a varchar2(500));
过程A
**********************************************************************************
create or replace procedure a is
v_sql varchar2(50);
v_ErrorMsg varchar2(500);
begin
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' 1');
commit;
v_sql:='drop table log';
execute immediate v_sql;
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' 2');
commit;
v_sql:='create table log (a varchar2(500))';
execute immediate v_sql;
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' 3');
commit;
insert into log values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' aa');
commit;
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' 4');
commit;
b;
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' 5');
commit;
exception when others then
v_ErrorMsg := 'a: '||sqlerrm;
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||v_ErrorMsg);
commit;
end a;
***************************************************************************************
过程B
create or replace procedure b is
vv varchar2(200);
v_ErrorMsg varchar2(500);
begin
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' b1');
commit;
insert into log values(to_char(sysdate)||' a_2');
commit;
insert into log1 values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||' b2');
commit;
vv:='hello word hi';
insert into log values(to_char(sysdate)||vv);
commit;
exception when others then
v_ErrorMsg := 'a: '||sqlerrm;
insert into log values(to_char(sysdate,'yyyy-mm-dd hh:mi:ss')||v_ErrorMsg);
end b;
********************************************************************************
我们看到过程A调用过程B之前先drop了表log,再重建了表log。运行A完毕后,我们看看表log1记录了什么:
select * from log1;
2005-01-27 11:55:18 1
2005-01-27 11:55:18 2
2005-01-27 11:55:18 3
2005-01-27 11:55:18 4
2005-01-27 11:55:18a: ORA-06508: PL/SQL: could not find program unit being called
如果再把过程A里的捕获exception代码去掉,我们会发现,执行A后,会报错,但是再看log1,我们会发现1,2,3,4有两次循环,就是说过程A先碰到错误后,重新执行了一遍自己,第二次碰到调用B时才报错停止。
我得到的解决办法就是不能drop掉那个表log后再重建,可以用truncate和insert,但这也会在某些地方引起麻烦,不知道各位有什么好的意见。