create or replace procedure aa_zhou_tt is
prod_inst number(12);
detail_flag number;
v_exe varchar2(4000);
crm_str varchar2(512) := ' select * from nc_gouqi_pricing_state a where a.remark=''Y''';
begin
amdocs.clear_tab('amdocs.tmp_3104_offer_detail');
v_exe := 'create table amdocs.tmp_3104_offer_detail as ' || crm_str ;
execute immediate v_exe;
v_exe := 'alter table amdocs.tmp_3104_offer_detail add desc_str varchar2(512)' ;
execute immediate v_exe;
for cur in (select distinct crm2_prod_offer_inst_id from amdocs.tmp_3104_offer_detail where rownum < 100) loop
dbms_output.put_line(cur.crm2_prod_offer_inst_id);
end loop;
dbms_transaction.commit;
end;
这里的对比04068的情况。
同样是使用了动态语句。但是这个能够正确定位amdocs.tmp_3104_offer_detail 。这是因为在过程的编译处理是预编译,使得amdocs.tmp_3104_offer_detail 能够正确取得地址,编译处理也是以过程为单位的。
而报04068错误的,是因为在调用另一个过程时,会动态重编译。它跟上层的过程尽管不是同一个单位,预编译过程也会不管代码层次,批量处理代码堆栈中所有代码。第一层代码会正确解析动态运行时的地址,嵌套下的调用程序却不一定,它在预编译时记录的预编译生成的地址,在运行过程中,老地址失效了,生成了新地址,嵌套的子程序如果不动态重编,就会读不到新地址:报错对象失效 04068。
这里采用的办法是将子程序动态重编译。用动态调用的方法来重新取程序。但会使得程序的效率降低。(包含编译时间、运行时间、编译内存开销、运行时内存开销等。在网上看到说oracle想将子程序对新地址的解析像上层程序一样,所以说是bug,想在12g解决)。
最重要的不是解决错误,而是对程序的体会,对内存处理方式和编译运行、和整个代码结构的体会。同时还有考虑运行的效率。