パッケージに状態があり、ヘッダーが変更されると、最初の呼び出しは次のようなエラースタックを取得します。
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package "LRIFFEL.PKG1" has been invalidated
ORA-04065: not executed, altered or dropped package "LRIFFEL.PKG1"
ORA-06508: PL/SQL: could not find program unit being called: "LRIFFEL.PKG1"
ORA-06512: at "LRIFFEL.PKG2", line 7
ORA-06512: at line 1
同じセッションからの後続の呼び出しは、パッケージの状態を再初期化するため、正常に実行されます。興味深いのは、呼び出し側が例外をキャッチしてraise_application_errorを実行すると、この動作が変化するように見えることです。予想どおり、raise_application_errorがスタックに含まれていますが、予想に反して、ORA-04068は含まれていません。次にエラースタックの例を示します。
ERROR at line 1:
ORA-20001: Failed
ORA-06512: at "LRIFFEL.PKG2", line 7
ORA-04061: existing state of package "LRIFFEL.PKG1" has been invalidated
ORA-04065: not executed, altered or dropped package "LRIFFEL.PKG1"
ORA-06508: PL/SQL: could not find program unit being called: "LRIFFEL.PKG1"
ORA-06512: at line 1
プロシージャを繰り返し呼び出すと同じエラーが発生し続けるため、これは表示の問題のようではありません。 raise_application_errorを単純なレイズに戻す(または例外ブロックを完全に排除する)場合にのみ、次の実行にORA-04068が含まれ、次の実行が成功します。
誰かがこの動作を確認および/または説明できますか?これは動作を再現するためのレシピです:
--Session 1 - Create Objects
create or replace package pkg1 as
vInteger Integer := 7;
procedure procA;
end;
/
create or replace
package body pkg1 as
procedure procA is
begin
DBMS_Output.Put_Line('ProcA');
end;
end;
/
create or replace
package pkg2 as
procedure procB;
end;
/
create or replace
package body pkg2 as
procedure procB is
begin
pkg1.procA;
exception
when others then
raise;
end;
end;
/
--Session 2 - Test execution.
execute pkg2.procB;
--Session 1 - Change package header and thus invalidate package state.
create or replace package pkg1 as
vInteger Integer := 8;
procedure procA;
end;
/
--Session 2 - Observe failure due to changed package state.
execute pkg2.procB;
--Session 2 - Observe success due to re-initialized package state.
execute pkg2.procB;
--Session 1 - Change Raise to Raise_Application_Error.
create or replace
package body pkg2 as
procedure procB is
begin
pkg1.procA;
exception
when others then
raise_application_error(-20001,'Failed',True);
end;
end;
/
--Session 1 - Change package header and thus invalidate package state.
create or replace package pkg1 as
vInteger Integer := 9;
procedure procA;
end;
/
--Session 2 - Observe failure due to changed package state.
execute pkg2.procB;
--Session 2 - Observe unexpected continued failures.
execute pkg2.procB;
execute pkg2.procB;
execute pkg2.procB;
execute pkg2.procB;
execute pkg2.procB;
execute pkg2.procB;
execute pkg2.procB;
--Session 1 - Change back to raise.
create or replace
package body pkg2 as
procedure procB is
begin
pkg1.procA;
exception
when others then
raise;
end;
end;
/
--Session 2 - Observe failure on the first execution.
execute pkg2.procB;
--Session 2 - Observe success.
execute pkg2.procB;
トリガーが含まれることを除いて、バグ229349は似ています。
Oracleからの応答は、アプリケーションが4068をキャッチして処理するため、これは実際にはバグではなく、エラーの通常の解決が行われないことです。パッケージがORA-01476-Divide By Zeroをスローする場合(たとえば)、raise_application_errorを実行しても、ORA-01476がスタックに含まれているかどうかに影響しないため、それらの説明は私には適切ではないようです。