プライマリ・コンテンツに移動
Pro*C/C++プログラマーズ・ガイド
12c リリース1(12.1)
B71397-03
目次へ移動
目次
索引へ移動
索引

前
次

方法2の使用方法

方法1では1ステップで実行し、方法2では2ステップに分けて実行します。動的SQL文(問合せは不可)は、まずPREPARE(名前の指定と解析)され、次にEXECUTEされます。

方法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が含まれています。

... 
int emp_number    INTEGER; 
char delete_stmt[120], search_cond[40];; 
... 
strcpy(delete_stmt, "DELETE FROM EMP WHERE EMPNO = :n AND "); 
printf("Complete the following statement's search condition--\n"); 
printf("%s\n", delete_stmt); 
gets(search_cond); 
strcat(delete_stmt, search_cond); 
 
EXEC SQL PREPARE sql_stmt FROM :delete_stmt; 
for (;;) 
{ 

    printf("Enter employee number: "); 
    gets(temp);
    emp_number = atoi(temp); 
    if (emp_number == 0) 
        break; 
    EXEC SQL EXECUTE sql_stmt USING :emp_number; 
} 
... 

方法2では、プリコンパイル時に入力ホスト変数のデータ型がわかっている必要があります。最後の例では、emp_numberintとして宣言されています。Oracleでは、floatcharなど、全データ型のOracle内部NUMBERデータ型への変換がサポートされるため、これをfloatまたはcharとして宣言することも可能です。

USING句

SQL文がEXECUTEされると、USING句の入力ホスト変数は、PREPAREされた動的SQL文内の該当するプレースホルダに置換されます。

PREPAREされた動的SQL文のプレースホルダは、それぞれが必ずUSING句の個別のホスト変数に対応している必要があります。つまり、PREPAREされた文に同じプレースホルダが2回以上現れるときは、それぞれがUSING句のホスト変数に対応している必要があります。

プレースホルダの名前は、ホスト変数の名前と一致する必要はありません。ただし、PREPARE済動的SQL文のプレースホルダの順序は、USING句の対応するホスト変数の順序と一致する必要があります。

USING句のホスト変数のうち1つでも配列がある場合は、すべてのホスト変数が配列であることが必要です。

NULLを指定するために、標識変数をUSING句のホスト変数と対応付けることができます。

関連項目:

標識変数

サンプル・プログラム: 動的SQL方法2

次のプログラムでは、動的SQL方法2を使用して2つの行をEMP表に挿入し、その後でそれらの行を削除しています。このプログラムはdemoディレクトリのsample7.pcファイルにあり、オンラインで利用できます。

/*
 *  sample7.pc: Dynamic SQL Method 2
 *
 *  This program uses dynamic SQL Method 2 to insert two rows into
 *  the EMP table, then delete them.
 */

#include <stdio.h>
#include <string.h>

#define USERNAME "SCOTT"
#define PASSWORD "TIGER"

/* Include the SQL Communications Area, a structure through
 * which ORACLE makes runtime status information such as error
 * codes, warning flags, and diagnostic text available to the
 * program.
 */
#include <sqlca.h>

/* Include the ORACLE Communications Area, a structure through
 * which ORACLE makes additional runtime status information
 * available to the program.
 */
#include <oraca.h>

/* The ORACA=YES option must be specified to enable use of
 * the ORACA.
 */
EXEC ORACLE OPTION (ORACA=YES);

char    *username = USERNAME;
char    *password = PASSWORD;
VARCHAR  dynstmt[80];
int      empno   = 1234;
int      deptno1 = 97;
int      deptno2 = 99;


/* Handle SQL runtime errors. */
void dyn_error();


main()
{
/* Call dyn_error() whenever an error occurs
 * processing an embedded SQL statement.
 */
    EXEC SQL WHENEVER SQLERROR DO dyn_error("Oracle error");

/* Save text of current SQL statement in the ORACA if an
 * error occurs.
 */
    oraca.orastxtf = ORASTFERR;

/* Connect to Oracle. */

    EXEC SQL CONNECT :username IDENTIFIED BY :password;
    puts("\nConnected to Oracle.\n");

/* Assign a SQL statement to the VARCHAR dynstmt.  Both
 * the array and the length parts must be set properly.
 * Note that the statement contains two host-variable
 * placeholders, v1 and v2, for which actual input
 * host variables must be supplied at EXECUTE time.
 */
    strcpy(dynstmt.arr,
        "INSERT INTO EMP (EMPNO, DEPTNO) VALUES (:v1, :v2)");
    dynstmt.len = strlen(dynstmt.arr);

/* Display the SQL statement and its current input host
 * variables.
 */
    puts((char *) dynstmt.arr);
    printf("   v1 = %d,  v2 = %d\n", empno, deptno1);

/* The PREPARE statement associates a statement name with
 * a string containing a SQL statement.  The statement name
 * is a SQL identifier, not a host variable, and therefore
 * does not appear in the Declare Section.

 * A single statement name can be PREPAREd more than once,
 * optionally FROM a different string variable.
 */
    EXEC SQL PREPARE S FROM :dynstmt;

/* The EXECUTE statement executes a PREPAREd SQL statement
 * USING the specified input host variables, which are
 * substituted positionally for placeholders in the
 * PREPAREd statement.  For each occurrence of a
 * placeholder in the statement there must be a variable
 * in the USING clause.  That is, if a placeholder occurs
 * multiple times in the statement, the corresponding
 * variable must appear multiple times in the USING clause.
 * The USING clause can be omitted only if the statement
 * contains no placeholders.
 *
 * A single PREPAREd statement can be EXECUTEd more
 * than once, optionally USING different input host
 * variables.
 */
    EXEC SQL EXECUTE S USING :empno, :deptno1;

/* Increment empno and display new input host variables. */

    empno++;
    printf("   v1 = %d,  v2 = %d\n", empno, deptno2);

/* ReEXECUTE S to insert the new value of empno and a
 * different input host variable, deptno2.
 * A rePREPARE is unnecessary.
 */
    EXEC SQL EXECUTE S USING :empno, :deptno2;

/* Assign a new value to dynstmt. */

    strcpy(dynstmt.arr,
        "DELETE FROM EMP WHERE DEPTNO = :v1 OR DEPTNO = :v2");
    dynstmt.len = strlen(dynstmt.arr);

/* Display the new SQL statement and its current input host
 * variables.
 */
    puts((char *) dynstmt.arr);
    printf("   v1 = %d,    v2 = %d\n", deptno1, deptno2);

/* RePREPARE S FROM the new dynstmt. */

    EXEC SQL PREPARE S FROM :dynstmt;

/* EXECUTE the new S to delete the two rows previously
 * inserted.
 */
    EXEC SQL EXECUTE S USING :deptno1, :deptno2;

/* Commit any pending changes and disconnect from Oracle. */

    EXEC SQL COMMIT RELEASE;
    puts("\nHave a good day!\n");
    exit(0);
}


void 
dyn_error(msg)
char *msg;
{
/* This is the ORACLE error handler.
 * Print diagnostic text containing error message,
 * current SQL statement, and location of error.
 */
    printf("\n%s", msg);
    printf("\n%.*s\n",
        sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
    printf("in \"%.*s...\"\n",
        oraca.orastxt.orastxtl, oraca.orastxt.orastxtc);
    printf("on line %d of %.*s.\n\n",
        oraca.oraslnr, oraca.orasfnm.orasfnml,
        oraca.orasfnm.orasfnmc);

/* Disable ORACLE error checking to avoid an infinite loop
 * should another error occur within this routine.
 */
    EXEC SQL WHENEVER SQLERROR CONTINUE;

/* Roll back any pending changes and 
 * disconnect from Oracle.
 */
    EXEC SQL ROLLBACK RELEASE;
    exit(1);
}