DBMS_DDLサブプログラムによるPL/SQLソース・テキストのラップ
DBMS_DDL
パッケージには、WRAP
ファンクションおよびCREATE_WRAPPED
プロシージャが含まれていて、各ファンクションおよびプロシージャは、動的に生成された単一のラップ可能PL/SQLユニットのPL/SQLソース・テキストをラップします。また、DBMS_DDL
パッケージには、WRAPまたはCREATE_WRAPPED
への入力が有効なラップ可能PL/SQLユニットでない場合に発生する、例外MALFORMED_WRAP_INPUT
(ORA-24230)も含まれます。(ラップ可能PL/SQLユニットのリストは、「PL/SQLのソース・テキストのラップ」の概要を参照してください。)
各WRAP
ファンクションは、ラップ可能PL/SQLユニットを作成する単一のCREATE
文を入力として取得し、PL/SQLソース・テキストがラップされた同等のCREATE
文を戻します。WRAP
ファンクションの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
注意:
DBMS_DDL
.WRAP
によって戻される文を、データ型がVARCHAR2A
の仮パラメータstatement
を含むDBMS_SQL
.PARSE
プロシージャに渡す場合、DBMS_SQL
.PARSE
のlfflg
パラメータをFALSE
に設定する必要があります。設定しないと、DBMS_SQL
.PARSE
によって、ラップされたPL/SQLユニットに行が追加され、ユニットが破損します。(DBMS_SQL
.PARSE
の構文は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。)
各CREATE_WRAPPED
プロシージャは、その対応するWRAP
ファンクションと同じ処理を行って、戻されたCREATE
文を実行し、指定されたPL/SQLユニットを作成します。CREATE_WRAPPED
プロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
ヒント:
DBMS_DDL
サブプログラムの起動時には、パッケージの完全修飾名SYS.DBMS_DDL
を使用し、他のユーザーがDBMS_DDL
という名前のローカル・パッケージを作成していたり、パブリック・シノニムDBMS_DDL
を定義している場合に発生する名前の競合を回避します。
ノート:
WRAP
ファンクションまたはCREATE_WRAPPED
プロシージャに入力されるCREATE
文は、そのサブプログラムを起動したユーザーの権限で実行されます。
例A-4では、EXECUTE
IMMEDIATE
文を使用してパッケージ仕様部を、およびCREATE_WRAPPED
プロシージャを使用してラップされたパッケージ本体を動的に作成します。
例A-5では、例A-4で作成したパッケージemp_actions
のテキストを選択し、プロシージャemp_actions.raise_salary
を起動します。パッケージ仕様部がラップされている場合、プロシージャを起動するために必要な情報は、パッケージ本体のPL/SQLソース・テキストのように判読不可能になります。
例A-4 CREATE_WRAPPEDプロシージャによるラップされたパッケージ本体の作成
DECLARE
package_text VARCHAR2(32767); -- text for creating package spec and body
FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'CREATE PACKAGE ' || pkgname || ' AUTHID CURRENT_USER AS
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
END ' || pkgname || ';';
END generate_spec;
FUNCTION generate_body (pkgname VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'CREATE PACKAGE BODY ' || pkgname || ' AS
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS
BEGIN
UPDATE employees
SET salary = salary + amount WHERE employee_id = emp_id;
END raise_salary;
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM employees WHERE employee_id = emp_id;
END fire_employee;
END ' || pkgname || ';';
END generate_body;
BEGIN
package_text := generate_spec('emp_actions'); -- Generate package spec
EXECUTE IMMEDIATE package_text; -- Create package spec
package_text := generate_body('emp_actions'); -- Generate package body
SYS.DBMS_DDL.CREATE_WRAPPED(package_text); -- Create wrapped package body
END;
/
例A-5 ラップされた本体を含むパッケージの表示およびパッケージ・プロシージャの起動
パッケージのテキストの選択:
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
結果:
cTEXT
------------------------------------------------------------------------
PACKAGE emp_actions AUTHID CURRENT_USER AS
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
END emp_actions;
PACKAGE BODY emp_actions wrapped
a000000
1f
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
b
180 113
1fOVodewm7j9dBOmBsiEQz0BKCgwg/BKoZ4VZy/pTBIYo8Uj1sjpbEz08Ck3HMjYq/Mf0XZn
u9D0Kd+i89g9ZO61I6vZYjw2AuBidnLESyR63LHZpFD/7lyDTfF1eDY5vmNwLTXrFaxGy243
0lHKAzmOlwwfBWylkZZNi2UnpmSIe6z/BU2nhbwfpqd224p69FwYVXmFX2H5IMsdZ2/vWsK9
cDMCD1KEqOnPpbU2yXdpW3GIbGD8JFIbKAfpJLkoLfVxoRPXQfj0h1k=
raised_salary
の起動およびその影響の表示:
DECLARE
s employees.salary%TYPE;
BEGIN
SELECT salary INTO s FROM employees WHERE employee_id=130;
DBMS_OUTPUT.PUT_LINE('Old salary: ' || s);
emp_actions.raise_salary(130, 100);
SELECT salary INTO s FROM employees WHERE employee_id=130;
DBMS_OUTPUT.PUT_LINE('New salary: ' || s);
END;
/
結果:
Old salary: 2800
New salary: 2900
PL/SQL procedure successfully completed.