2016-06-21 52 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; 

這裏是輸出

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 

這需要5到10分鐘左右以發生超時。

我們如何解鎖要重新編譯的對象?

+2

過程無法在會話/事務中使用時重新編譯。由於您正在使用並嘗試在同一個會話中重新編譯代碼,因此此設計將無法工作。你想達到什麼目的?可能有更好的方法。 –

+1

您的匿名塊不能具有對匿名塊嘗試重新編譯的對象的靜態引用。你已經註釋掉了'execute immediate'行來調用'dbms_output'。我假設你最初嘗試過,並且它已經起作用,然後你將它改爲靜態引用「執行」調用。這是行不通的 - 兩個電話都需要動態。 –

回答

1

正如評論中所述,完全不可能通過您嘗試完成工作的方式。我建議你應該直接調用RECOMPILE過程而不是recompile_usage,希望在snippet幫助下。

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