ORA-04068: existing state of packages has been discarded

张维照 2019-05-31
9
0 0
摘要:执行的时候,Oracle则不会再进行类似的检查,而是直接运行过程,这也是存储过程拥有较高效率的原因之一。

问题描述

SQL> conn anbob
Enter password:
Connected.
SQL> create table test (id int,name varchar2(10));

Table created.

SQL> create or replace p_replace
  2
SQL>
SQL> create or replace procedure p_replace
  2  is
  3  begin
  4  execute immediate 'drop table test';
  5  execute immediate 'create table test (id int,name varchar2(10))';
  6  end;
  7  /

Procedure created.

SQL> create or replace procedure p_insert
  2  is
  3  begin
  4  insert into  test values(trunc(dbms_random.value(10,1000)),'anbob.com');
  5  commit;
  6  end;
  7  /

Procedure created.

SQL> begin
  2  p_replace;
  3  p_insert;
  4  end;
  5  /
begin
*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "ANBOB.P_REPLACE", line 5
ORA-06512: at line 2

SQL> conn system/oracle
Connected.

SQL> grant create table to anbob;

Grant succeeded.

SQL> conn anbob/anbob
Connected.

SQL> begin
  2  p_replace;
  3  p_insert;
  4  end;
  5  /
begin
*
ERROR at line 1:
ORA-04068: existing state of packages has been discarded
ORA-04065: not executed, altered or dropped stored procedure "ANBOB.P_INSERT"
ORA-06508: PL/SQL: could not find program unit being called: "ANBOB.P_INSERT"
ORA-06512: at line 3

SQL> exec p_replace;

PL/SQL procedure successfully completed.

SQL> exec p_insert;

PL/SQL procedure successfully completed.

SQL> select * from test;

        ID NAME
---------- ----------
       231 anbob.com

SQL> begin
  2  exec p_replace;
  3  execute immidate 'begin p_insert;end;';
  4  end;
  5  /
exec p_replace;
     *
ERROR at line 2:
ORA-06550: line 2, column 6:
PLS-00103: Encountered the symbol "P_REPLACE" when expecting one of the
following:
:= . ( @ % ;

SQL> l2
  2* exec p_replace;
SQL> c /exec/
  2*  p_replace;
        *
ERROR at line 3:
ORA-06550: line 3, column 9:
PLS-00103: Encountered the symbol "IMMIDATE" when expecting one of the
following:
:= . ( @ % ; immediate
The symbol ":= was inserted before "IMMIDATE" to continue.

SQL> l
  1  begin
  2   p_replace;
  3  execute immidate 'begin p_insert;end;';
  4* end;
SQL> l3
  3* execute immidate 'begin p_insert;end;';
SQL> c /immidate/immediate
  3* execute immediate 'begin p_insert;end;';
SQL> l
  1  begin
  2   p_replace;
  3  execute immediate 'begin p_insert;end;';
  4* end;
SQL> run
  1  begin
  2   p_replace;
  3  execute immediate 'begin p_insert;end;';
  4* end;

PL/SQL procedure successfully completed.

SQL> select * from test;

        ID NAME
---------- ----------
       274 anbob.com

SQL>


专家解答

存储过程在编译时,自动检查语法错误、权限以及所有对象的依赖性。而等到执行的时候,Oracle则不会再进行类似的检查,而是直接运行过程,这也是存储过程拥有较高效率的原因之一。
当存储过程所依赖的对象发生了变化,Oracle会自动将存储过程的状态置为INVALID,而存储过程的状态如果为INVALID,则会在下次执行时尝试重新编译,如果编译通过则继续执行;如果编译失败则报错。

在调用P_INSERT_T过程之前对P_INSERT_T进行检查并重新编译,所以采用动态SQL不会报错


「喜欢文章,快来给作者赞赏墨值吧」

评论

0
0
Oracle
订阅
欢迎订阅Oracle频道,订阅之后可以获取最新资讯和更新通知。
墨值排行
今日本周综合
近期活动
全部
相关课程
全部