Dynamic SQL¶
</ div>
動的SQL *は、コマンドが実行される直前まで不明なSQLコマンドを実行機能を提供する手法です。これまで、SPLプログラムで示されたSQLコマンドは静的SQLでした-プログラム自分自身が実行を開始する前に、完全なコマンド(変数を例外)を認識してプログラムにコーディングする必要があります。したがって、動的SQLを使用すると、実行されたSQLはプログラムのランタイム中に変更される可能性があります。
さらに、動的SQLは、CREATE TABLEなどのデータ定義コマンドをSPLプログラム内から実行できる唯一のメソッドです。
ただし、動的SQLのランタイムパフォーマンスは静的SQLよりも遅くなることに注意してください。
EXECUTE IMMEDIATEコマンドは、
SQLコマンドを動的に実行するために使用されます。
EXECUTE IMMEDIATE '<sql_expression>;'
* [ INTO { <variable> [, ...] | <record> } ]
* [ USING <expression> [, ...] ]
sql_expressionは、動的に実行されるSQLコマンドを含む文字列式です。
variableは、通常、sql_expressionでSQLコマンドを実行した結果として作成されたSELECTコマンドから結果セットの出力を受け取ります。変数の数、オーダー、およびタイプは、数、マッチ、および結果セットのフィールドとタイプ互換オーダーがなければなりません。あるいは、レコードのフィールドが番号オーダーにマッチし、結果セットと型互換性がある限り、recordを指定できます。
INTO句を使用する場合、結果セットで正確に1つの行を返す必要があります。そうしないと、例外が発生します。
USING句を使用すると、expressionの値がプレースホルダに渡されます。プレースホルダーは、変数を使用できるsql_expressionのSQLコマンド内に埋め込みれて表示されます。プレースホルダーは、コロン(:)プレフィックス付きの識別子-:nameで示されます。評価された式の数、オーダー、および結果のデータ型は、番号、オーダーとマッチし、sql_expressionのプレースホルダーと型互換性がある必要があります。プレースホルダーはSPLプログラムのどこにも宣言されていないことに注意してください-sql_expressionにのみ表示されます。
次の例は、基本的な動的SQLコマンドを文字列リテラルとして示しています。
DECLARE
* v_sql VARCHAR2(50);
BEGIN
* EXECUTE IMMEDIATE 'CREATE TABLE job (jobno NUMBER(3),' ||
* ' jname VARCHAR2(9))';
* v_sql := 'INSERT INTO job VALUES (100, ''ANALYST'')';
* EXECUTE IMMEDIATE v_sql;
* v_sql := 'INSERT INTO job VALUES (200, ''CLERK'')';
* EXECUTE IMMEDIATE v_sql;
END;
次の例は、
SQL文字列のプレースホルダーに値を渡すUSING句を示しています。
DECLARE
* v_sql VARCHAR2(50) := 'INSERT INTO job VALUES ' ||
* '(:p_jobno, :p_jname)';
* v_jobno job.jobno%TYPE;
* v_jname job.jname%TYPE;
BEGIN
* v_jobno := 300;
* v_jname := 'MANAGER';
* EXECUTE IMMEDIATE v_sql USING v_jobno, v_jname;
* v_jobno := 400;
* v_jname := 'SALESMAN';
* EXECUTE IMMEDIATE v_sql USING v_jobno, v_jname;
* v_jobno := 500;
* v_jname := 'PRESIDENT';
* EXECUTE IMMEDIATE v_sql USING v_jobno, v_jname;
END;
次の例は、INTO句とUSING句の両方を示しています。
SELECTコマンドを最後に実行すると、個々の変数ではなくレコードに結果が返されることに注意してください。
DECLARE
* v_sql VARCHAR2(60);
* v_jobno job.jobno%TYPE;
* v_jname job.jname%TYPE;
* r_job job%ROWTYPE;
BEGIN
* DBMS_OUTPUT.PUT_LINE('JOBNO JNAME');
* DBMS_OUTPUT.PUT_LINE('----- -------');
* v_sql := 'SELECT jobno, jname FROM job WHERE jobno = :p_jobno';
* EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 100;
* DBMS_OUTPUT.PUT_LINE(v_jobno || ' ' || v_jname);
* EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 200;
* DBMS_OUTPUT.PUT_LINE(v_jobno || ' ' || v_jname);
* EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 300;
* DBMS_OUTPUT.PUT_LINE(v_jobno || ' ' || v_jname);
* EXECUTE IMMEDIATE v_sql INTO v_jobno, v_jname USING 400;
* DBMS_OUTPUT.PUT_LINE(v_jobno || ' ' || v_jname);
* EXECUTE IMMEDIATE v_sql INTO r_job USING 500;
* DBMS_OUTPUT.PUT_LINE(r_job.jobno || ' ' || r_job.jname);
END;
以下は、前の匿名ブロックからの出力です。
JOBNO JNAME
----- -------
100 ANALYST
200 CLERK
300 MANAGER
400 SALESMAN
500 PRESIDENT
BULK COLLECT句を使用して、EXECUTE IMMEDIATEステートメントの結果セットを名前付けコレクションにアセンブルできます。
BULK COLLECT句の使用については、Using the BULK COLLECT
Clause、EXECUTE IMMEDIATE BULK COLLECTを参照してください。