"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