2016-06-21 146 views
1

plsql用のモック・ライブラリを実装しようとしています。 格納されたオブジェクトを動的に再コンパイルしようとすると、ORA-04021エラーが発生します。ORA-04021再コンパイル時

コードが

create or replace function perform return varchar2 is begin return 'zero'; end; 
/

create or replace procedure recompile(source in clob) 
is 
begin 
    execute immediate source; 
end; 
/

create or replace procedure recompile_usage 
is 
begin 
    recompile('create or replace function perform return varchar2 is begin return ''one''; end;'); 

    dbms_output.put_line(perform); 
    --execute immediate 'begin dbms_output.put_line(perform); end;'; 

    recompile('create or replace function perform return varchar2 is begin return ''two''; end;'); 
    dbms_output.put_line(perform); 

end; 
/

exec recompile_usage; 

であり、ここでそれが発生するタイムアウトのために約5〜10分かかり、出力

Function created. 

Procedure created. 

Procedure created. 

one 
BEGIN recompile_usage; END; 

* 
ERROR at line 1: 
ORA-04021: timeout occurred while waiting to lock object 
ORA-06512: at "UTP.RECOMPILE", line 4 
ORA-06512: at "UTP.RECOMPILE_USAGE", line 9 
ORA-06512: at line 1 

です。

再コンパイルするオブジェクトのロックを解除するにはどうすればよいですか?

+2

プロシージャは、セッション/トランザクションで使用中は再コンパイルできません。同じセッションでコードを使用して再コンパイルしようとしているので、この設計はうまくいかないでしょう。あなたは何を達成しようとしていますか?より良い方法があるかもしれません。 –

+1

あなたの匿名ブロックは、匿名ブロックが再コンパイルしようとしているオブジェクトへの静的参照を持つことはできません。 'dbms_output'を呼び出す' execute immediate'行をコメントアウトしました。私はあなたが最初にそれを試したと仮定し、次にそれを変更して 'perform'呼び出しに対する静的な参照を持つようにしました。それはうまくいきません - 両方の呼び出しが動的である必要があります。 –

答えて

1

コメントに完全に記載されているように、あなたが仕事を達成しようとしている方法では不可能です。 recompile_usageではなくRECOMPILEプロシージャを直接呼び出すことをお勧めします。

set sqlbl on; 
set define off; 

DECLARE 
    lv_sql VARCHAR2(32676); 
BEGIN 
    RECOMPILE(
    'create or replace function perform return varchar2 is begin return ''one''; end;' 
); 
    recompile(
    'create or replace function perform return varchar2 is begin return ''two''; end;' 
); 
END; 

-----------------------------OUTPUT-------------------------------------------- 

anonymous block completed 

SELECT OBJECT_NAME,OBJECT_TYPE,STATUS FROM ALL_OBJECTS 
WHERE object_name = 'PERFORM'; 


**OBJECT_NAME OBJECT_TYPE STATUS** 
PERFORM   FUNCTION VALID 
関連する問題