"ORA-06508 PL/SQL: コールしているプログラム単位が見つかりませんでした"
というエラーが発生することがあります。
例えば、IDを採番する順序とその順序からIDを取得してテーブルにデータを挿入するプロシージャがあり、
CREATE SEQUENCE ID_SEQ NOCACHE; CREATE OR REPLACE PROCEDURE TABLE1_INSERT_PROC ( p_name IN VARCHAR2, p_id OUT NUMBER ) IS wk_id NUMBER(38); BEGIN SELECT ID_SEQ.NEXTVAL INTO wk_id FROM DUAL; INSERT INTO TABLE1 ( ID, NAME ) VALUES ( wk_id, p_name ) RETURNING ID INTO p_id; END; /
以下のように、動的SQLを使用して一旦順序を削除/作成してからプロシージャを実行するようなPL/SQLを実行した場合、
DECLARE wk_id NUMBER(38); BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE ID_SEQ'; EXECUTE IMMEDIATE 'CREATE SEQUENCE ID_SEQ NOCACHE'; TABLE1_INSERT_PROC ( 'name1', wk_id ); DBMS_OUTPUT.PUT_LINE ( 'id = ' || wk_id ); END; /
以下のようなエラーが発生します。
行1でエラーが発生しました。: ORA-04068: パッケージの既存状態は廃棄されました。 ORA-04064: 実行されませんでした。procedure "SCOTT.TABLE1_INSERT_PROC"は無効になりました ORA-06508: PL/SQL: コールしているプログラム単位が見つかりませんでした ORA-06512: 行6
PL/SQLブロックはブロック全体を解析してから実行されます。
そのため、順序が再作成されたことにより、それを利用しているプロシージャも変更されて解析時と実行時で互換性が取れなくなり、上記のエラーが発生するようです。
このエラーを避けるには、以下のようにDDL文を別ブロックに切り出すか、
DROP SEQUENCE ID_SEQ / CREATE SEQUENCE ID_SEQ NOCACHE / DECLARE wk_id NUMBER(38); BEGIN TABLE1_INSERT_PROC ( 'name1', wk_id ); DBMS_OUTPUT.PUT_LINE ( 'id = ' || wk_id ); END; /
または、プロシージャの実行にも動的SQLを使用するという方法が考えられます。
DECLARE wk_id NUMBER(38); BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE ID_SEQ'; EXECUTE IMMEDIATE 'CREATE SEQUENCE ID_SEQ NOCACHE'; EXECUTE IMMEDIATE 'BEGIN TABLE1_INSERT_PROC ( :1, :2 ); END;' USING 'name1', OUT wk_id; DBMS_OUTPUT.PUT_LINE ( 'id = ' || wk_id ); END; /
ただ、DDL文は実行すると自動的にコミットされてしまうので、このようなプログラムでエラーや障害が発生した場合、データの整合性を損なう危険性もあります。
故によっぽど必要に迫られない限りは、DDL文とDML文を混在させるようなプログラムは避けた方がいいでしょう。
【関連エントリ】
[Oracle] 動的SQLの実行(その1) 2005/01/18
[Oracle] 動的SQLの実行(その2) 2005/01/19
[Oracle] 動的SQLでDDL文を実行しているPL/SQLでORA-6508エラーが発生 2005/02/15