web-dev-qa-db-ja.com

PL / SQLパッケージが無効化されました

パッケージ(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を再コンパイルすると、値がリセットされます。

この例外がスローされるため、クライアントはこれらの変数に依存できなくなったことを認識できます。

ソリューション

  • 可能であれば、すべてのグローバル変数と定数(11gR2より前)をパッケージ本体から削除します
  • グローバル変数をDETERMINISTIC関数に置き換えます( この回答 で提案されているように)
  • PRAGMA SERIALLY_REUSABLE を使用してパッケージを定義すると、Oracleはサーバーを呼び出すたびにグローバル変数を再初期化します。
  • パッケージを再度呼び出す前に、セッションを閉じて再接続してください。
  • 状態を手動でリセットします( Paul Jamesの回答 を参照)
21
Peter Lang

スクリプトで何かを実行している場合は、再コンパイルされたコードを実行する前に、そこでこれらのコマンドを試してください。

exec DBMS_SESSION.RESET_PACKAGE
exec DBMS_SESSION.MODIFY_PACKAGE_STATE( DBMS_SESSION.REINITIALIZE )

彼らは名前が示唆するかもしれないことをします。

22
PaulJ

上記のエラー:ORA-06508:PL/SQL:呼び出されているプログラム・ユニットが見つかりませんでした。

見つからなかったストアドプログラムを呼び出そうとしたときに発生します。プログラムが削除されたか、互換性がないように変更されたか、エラーでコンパイルされた可能性があります。

パッケージ本体を含むすべての参照プログラムが存在し、互換性があることを確認してください。

このクエリを実行して無効なオブジェクトを見つけることができます。これにより、ORA-06508エラーが発生する可能性があります。

dba_registryからcomp_id、comp_name、version、status、namespace、schemaを選択します。

0
Paul

考えられる問題は次のとおりです。

  • 呼び出しているパッケージ/プロシージャが無効です(個別に呼び出された場合は機能しますが)このクエリで、パッケージのエントリまたはパッケージで使用されているオブジェクトがあるかどうかを確認してくださいall_objectsビュー

    select * from all_objects where status = 'INVALID' and owner = 'SCHEMA_NAME';

  • パッケージにグローバル変数があることを確認しますか?はいの場合、それらの変数が他のセッションによって変更されていないかどうかを確認します。できれば、これらのグローバル変数を削除し、関数を使用します。

  • 以下のスクリプトを実行して、スキーマ内のすべてのオブジェクトをコンパイルします

    dbms_utility.compile_schema( 'SCHEMA_NAME'、false);を開始します。終わり;

  • 上記のいずれも機能しない場合の最後のオプションは、パッケージからすべてのプロシージャ/関数を削除し、新しい関数を追加して、トリガーから関数を実行してみます。これが機能するかどうかを確認し、パッケージが特別にロックされていることを確認します。新しい関数/ procを追加した後、その状態は再び有効になり、実際のすべての関数/ procを追加して、新しく追加された関数/ procを削除できます。
0
Ankur Bhutani