パッケージ(PKG_MY_PACKAGE)を利用するスクリプトがあります。そのパッケージのクエリの一部のフィールドを変更してから再コンパイルします(他のパッケージは変更またはコンパイルしません)。スクリプトを実行すると、次のようなエラーが発生します
ORA-04068:パッケージの既存の状態が破棄されました ORA-04061:パッケージ本体「USER3.PKG_MY_PACKAGE」の既存の状態が無効になりました ORA-04065:実行されません。パッケージ本体 "USER3.PKG_MY_PACKAGE" ORA-06508:PL/SQL:呼び出されているプログラム・ユニットが見つかりませんでした: "USER3.PKG_MY_PACKAGE" ORA-06512:行34
(システム内の他の何も変更せずに)スクリプトを再度実行すると、スクリプトは正常に実行されます。
無効な参照を修正するスクリプトを実行する前にコンパイルしたとき、私は思った。これは100%再現可能であり、このスクリプトを使用すればするほど、煩わしくなります。何がこれを引き起こす可能性があり、何がそれを修正しますか?
(Oracle 10g、PL/SQL Developer 7を使用)
背景
existing state of packages has been discarded
は、パッケージに何らかの状態があったことを意味します。
これは、パッケージ本体に格納されているグローバル変数が原因で発生します。
11.2.0.2までは、定数もこの動作を引き起こしていました( ドキュメント を参照)。
パッケージはすでにセッションで使用されているため、Oracleはこの状態がユーザーに関連していると見なします。これらの変数の一部は現在異なる値を持っている可能性があり、Bodyを再コンパイルすると、値がリセットされます。
この例外がスローされるため、クライアントはこれらの変数に依存できなくなったことを認識できます。
ソリューション
DETERMINISTIC
関数に置き換えます( この回答 で提案されているように)PRAGMA SERIALLY_REUSABLE
を使用してパッケージを定義すると、Oracleはサーバーを呼び出すたびにグローバル変数を再初期化します。スクリプトで何かを実行している場合は、再コンパイルされたコードを実行する前に、そこでこれらのコマンドを試してください。
exec DBMS_SESSION.RESET_PACKAGE
exec DBMS_SESSION.MODIFY_PACKAGE_STATE( DBMS_SESSION.REINITIALIZE )
彼らは名前が示唆するかもしれないことをします。
上記のエラー:ORA-06508:PL/SQL:呼び出されているプログラム・ユニットが見つかりませんでした。
見つからなかったストアドプログラムを呼び出そうとしたときに発生します。プログラムが削除されたか、互換性がないように変更されたか、エラーでコンパイルされた可能性があります。
パッケージ本体を含むすべての参照プログラムが存在し、互換性があることを確認してください。
このクエリを実行して無効なオブジェクトを見つけることができます。これにより、ORA-06508エラーが発生する可能性があります。
dba_registryからcomp_id、comp_name、version、status、namespace、schemaを選択します。
考えられる問題は次のとおりです。
呼び出しているパッケージ/プロシージャが無効です(個別に呼び出された場合は機能しますが)このクエリで、パッケージのエントリまたはパッケージで使用されているオブジェクトがあるかどうかを確認してくださいall_objectsビュー
select * from all_objects where status = 'INVALID' and owner = 'SCHEMA_NAME';
パッケージにグローバル変数があることを確認しますか?はいの場合、それらの変数が他のセッションによって変更されていないかどうかを確認します。できれば、これらのグローバル変数を削除し、関数を使用します。
以下のスクリプトを実行して、スキーマ内のすべてのオブジェクトをコンパイルします
dbms_utility.compile_schema( 'SCHEMA_NAME'、false);を開始します。終わり;