方法1では1ステップで実行することを、方法2では2ステップに分けて実行します。動的SQL文(問合せは不可)は、まずPREPARE
(名前の指定および解析)され、その後実行されます。
方法2では、SQL文に入力ホスト変数およびインジケータ変数のプレースホルダを含めることができます。このSQL文は一度PREPARE
すれば、ホスト変数に別の値を指定して繰り返しEXECUTE
できます。また、COMMIT
またはROLLBACK
の後でSQL文を再度PREPAREする必要はありません(ログオフして再接続する場合を除く)。
方法4では非問合せにEXECUTE
を使用できます。
PREPARE
文の構文は次のとおりです。
EXEC SQL PREPARE statement_name FROM { :host_string | string_literal };
PREPARE
はSQL文を解析して名前を指定します。
statement_nameは、ホスト変数やプログラム変数ではなく、プリコンパイラで使用される識別子であり、宣言部で宣言されません。これはEXECUTE
の対象としてPREPARE
済の文を示しているにすぎません。
EXECUTE
文の構文は次のとおりです。
EXEC SQL EXECUTE statement_name [USING host_variable_list];
host_variable_listは、次の構文を表しています。
:host_variable1[:indicator1] [, host_variable2[:indicator2], ...]
解析されたSQL文は、各入力変数に指定した値を使用してEXECUTE
により実行されます。次の例では、入力されたSQL文に、プレースホルダnが含まれています。
EXEC SQL BEGIN DECLARE SECTION; ... emp_number INTEGER; delete_stmt CHARACTER(120); EXEC SQL END DECLARE SECTION; search_cond CHARACTER(40); ... set delete_stmt = 'DELETE FROM EMP WHERE EMPNO = :n AND '; display 'Complete the following statement's search condition:'; display delete_stmt; read search_cond; concatenate delete_stmt, search_cond; EXEC SQL PREPARE sql_stmt FROM :delete_stmt; LOOP display 'Enter employee number: '; read emp_number; IF emp_number = 0 THEN exit loop; EXEC SQL EXECUTE sql_stmt USING :emp_number; ENDLOOP;
方法2では、プリコンパイル時に入力ホスト変数のデータ型がわかっている必要があります。前の例では、emp_numberがINTEGER
型として宣言されています。これは、CHARACTER
型やREAL
型としても宣言できますが、これはOracleではこれらすべてのデータ型のNUMBER
データ型への変換がサポートされているためです。
SQL文がEXECUTE
されると、USING
句の入力ホスト変数は、PREPARE
済動的SQL文の対応するプレースホルダに置き換わります。
PREPAREされた動的SQL文内のプレースホルダはそれぞれ、USING
句のホスト変数に対応している必要があります。したがって、PREPARE
済の文に同じプレースホルダが2回以上現れる場合、それぞれがUSING
句のホスト変数に対応している必要があります。USING
句のホスト変数のうち1つでも配列があれば、すべてのホスト変数が配列であることが必要です。
プレースホルダの名前は、ホスト変数の名前と一致する必要はありません。ただし、PREPARE
済動的SQL文のプレースホルダの順序は、USING
句の対応するホスト変数の順序と一致する必要があります。
NULLを指定するために、インジケータ変数をUSING
句のホスト変数と関連付けることができます。詳細は、インジケータ変数の使用についてを参照してください
次のプログラムでは、UPDATE
文のWHERE
句で使用する検索条件の入力をユーザーに求め、その後方法2を使用してその文を準備し実行します。UPDATE
文のSET
句にはプレースホルダ(c)が含まれています。
EXEC SQL BEGIN DECLARE SECTION; username CHARACTER(20); password CHARACTER(20); sql_stmt CHARACTER(80); empno INTEGER VALUE 1234; deptno1 INTEGER VALUE 97; deptno2 INTEGER VALUE 99; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; EXEC ORACLE OPTION (ORACA=YES); EXEC SQL WHENEVER SQLERROR GOTO sql_error; display 'Username? '; read username; display 'Password? '; read password; EXEC SQL CONNECT :username IDENTIFIED BY :password; display 'Connected to Oracle'; set sql_stmt = 'INSERT INTO EMP (EMPNO, DEPTNO) VALUES (:v1, :v2)'; display "V1 = ", empno, "V2 = ", deptno1; EXEC SQL PREPARE S FROM :sql_stmt; EXEC SQL EXECUTE S USING :empno, :deptno1; set empno = empno + 1; display "V1 = ", empno, "V2 = ", deptno2; EXEC SQL EXECUTE S USING :empno, :deptno2; set sql_stmt = 'DELETE FROM EMP WHERE DEPTNO = :v1 OR DEPTNO = :v2")'; display "V1 = ", deptno1, "V2 = ", deptno2; EXEC SQL PREPARE S FROM :sql_stmt; EXEC SQL EXECUTE S USING :deptno1, :deptno2; EXEC SQL COMMIT WORK RELEASE; exit program; sql_error: EXEC SQL WHENEVER SQLERROR CONTINUE; display 'Processing error'; EXEC SQL ROLLBACK WORK RELEASE; exit program with an error;