SQLPrepare() - ステートメントを準備する
SQLPrepare() は、SQL ステートメントを入力ステートメント・ハンドルと関連付け、
そのステートメントを準備するためにデータベース管理システムに送ります。 アプリケーションは、ステートメント・ハンドルを他の関数に渡して、
この準備済みステートメントを参照することができます。
前に照会ステートメント (または結果セットを戻す関数) を用いて、ステートメント・ハンドルを使用している場合、SQLCloseCursor() を呼び出しカーソルをクローズしてから、SQLPrepare() を呼び出す必要があります。
SQLPrepare() の ODBC 仕様
| ODBC 仕様レベル | X/Open CLI CAE 仕様 | ISO CLI 仕様 |
|---|---|---|
| 1.0 | はい | はい |
構文
SQLRETURN SQLPrepare (SQLHSTMT hstmt,
SQLCHAR FAR *szSqlStr,
SQLINTEGER cbSqlStr);関数引数
次の表は、この関数のそれぞれの引数ごとに、 データ・タイプ、用途、および説明を示しています。
| データ・タイプ | 引数 | 使用 | 説明 |
|---|---|---|---|
| SQLHSTMT | hstmt | input | ステートメント・ハンドル。 hstmt に関連したオープン・カーソルがあってはなりません。 |
| SQLCHAR * | szSqlStr | input | SQL ステートメント・ストリング。 |
| SQLINTEGER | cbSqlStr | input | 引数 szSqlStr の内容の長さ (バイト)。 これは、szSqlstr の SQL ステートメントの正確な長さに設定するか、もしくは ステートメント・テキストが NUL 終了の場合は SQL_NTS に設定する必要があります。 |
使用法
SQL ステートメント・テキストにベンダー・エスケープ文節シーケンスが含まれる場合、Db2 ODBC は、準備用にデータベースに送信する前に、まず SQL ステートメント・テキストを適切な Db2 固有のフォーマットに変更します。 アプリケーションがベンダー・エスケープ文節シーケンスを含む SQL ステートメントを生成しない場合、Db2 ODBC がベンダー・エスケープ文節のスキャンを実行しないよう SQL_NOSCAN ステートメント属性をステートメント・レベルで SQL_NOSCAN_ON に設定する必要があります。
SQLPrepare() を使用してステートメントが準備されると、アプリケーションは、以下のものを呼び出して、結果セット (ステートメントが照会の場合) の形式に関する
情報を要求することができます。SQLNumResultCols()SQLDescribeCol()SQLColAttribute()
SQL ステートメント・ストリングには、パラメーター・マーカーが含まれている
場合があり、SQLNumParams() を呼び出して、ステートメントのパラメーター・マーカーの数を判別することができます。 パラメーター・マーカーは疑問符 (?) で表されます。これは、SQLExecute() が呼び出されたときに、アプリケーションの指定値に置き換えられるステートメント上の位置を示します。 バインド・パラメーター関数である SQLBindParameter() を使用して、アプリケーションの値を
それぞれのパラメーター・マーカーにバインド (関連付ける) し、さらにデータを転送する際に
データ変換を実施するかどうかを示します。
SQLExecute()を呼び出す前に、すべてのパラメーターをバインドする必要があります。
アプリケーションは、SQLExecute() 呼び出しからの結果を処理した後、新しい (または同じ) パラメーター値を使用して再度ステートメントを実行することができます。
この SQL ステートメントを COMMIT または ROLLBACK にすることはできま
せん。 SQLEndTran() を呼び出して、COMMIT または ROLLBACK を出す必要があり
ます。 Db2 for z/OS® がサポートするSQLステートメントの詳細については、「 Db2 ODBC と組み込みSQLの違い 」のトピックをご覧ください。
SQL ステートメントが定位置 DELETE または定位置 UPDATE の場合は、 そのステートメントで参照されるカーソルを、 同じ接続ハンドルおよび同じ分離レベルの個別のステートメント・ハンドルで定義する必要があります。
準備されたステートメントが MERGE ステートメントの場合、ステートメント・テキストに FOR n ROWS 文節を組み込むことはできません。 結合する行数を指定するには、 SQLSetStmtAttr() 関数を使用します。
戻りコード
SQLPrepare() は、呼び出された後、次のいずれかの値を戻します。- SQL_SUCCESS
- SQL_SUCCESS_WITH_INFO
- SQL_ERROR
- SQL_INVALID_HANDLE
診断
次の表は、この関数が生成する各 SQLSTATE 値ごとに、 その記述と説明を一覧で記載してあります。
| SQLSTATE | 説明 | 説明 |
|---|---|---|
| 01 5 04 | UPDATE または DELETE ステートメントに、WHERE 節がありません。 | szSqlStr に、WHERE 文節 がない UPDATE または DELETE ステートメントが含まれています。 |
| 08S01 | 通信リンク障害が発生しました。 | 関数が完了する前に、アプリケーションとデータ・ソース間の 通信リンクで障害が発生しました。 |
| 21S01 | 挿入値リストが列リストに一致していません。 | szSqlStr には INSERT または MERGE ステートメントが含まれており、 挿入される値の個数が派生表の程度と一致しませんでした。 |
| 21S02 | 派生表の次数が列リストに一致していません。 | szSqlStr には CREATE VIEW ステートメントが含まれており、 指定された名前の個数が照会仕様で定義された派生表と同じ程度ではありません。 |
| 24000 | カーソルの状態が無効です。 | カーソルはすでに、ステートメント・ハンドル上にオープンされています。 |
| 34000 | カーソル名が無効です。 | szSqlStr に位置付け DELETE または 位置付け UPDATE が含まれていますが、実行されるステートメントが参照するカーソルがオープンされていません。 |
| 37 xxx 1 | SQL 構文が無効です。 | szSqlStr に、1 つ以上の次のもの
が含まれています。
|
| 4000 1 | トランザクション・ロールバック。 | この SQL ステートメントが属しているトランザクションが、 デッドロックまたはタイムアウトのためにロールバックされます。 |
| 42 xxx 1 | 構文エラーまたはアクセス規則違反。 | これらの SQLSTATE は、以下のエラーのいずれかを示しています。
|
| 42S0 1 | データベース・オブジェクトは、既に存在しています。 | szSqlStr に、CREATE TABLE または CREATE VIEW ステートメントが 含まれていますが、指定された表名またはビュー名は既に存在しています。 |
| 42S02 | データベース・オブジェクトは存在しません。 | szSqlStr に、存在しない表名またはビュー名を参照 する SQL ステートメントが含まれています。 |
| 42S11 | 索引は既に存在しています。 | szSqlStr に CREATE INDEX ステートメント が含まれていますが、指定された索引名は既に存在しています。 |
| 42S12 | 索引が見つかりません。 | szSqlStr に DROP INDEX ステートメントが含まれてい ますが、指定された索引名が存在しません。 |
| 42S21 | 列はすでにあります。 | szSqlStr に ALTER TABLE ステートメントが含まれていますが、ADD 文節に指定された列 が固有でないか、または基本表内の既存の列を指定しています。 |
| 42S22 | 列が見つかりません。 | szSqlStr に、存在しない列名を参照 する SQL ステートメントが含まれています。 |
| 580 04 | 予想外のシステム障害が発生しました。 | リカバリー不能なシステム・エラーです。 |
| HY001 | メモリーの割り振りが失敗しました。 | DB2 ODBC は、関数の実行または完了をサポートするのに必要なメモリーを割り振ることができません。 |
| HY009 | NULL ポインターの使用が無効です。 | szSqlStr が NULL ポインターです。 |
| HY010 | 関数のシーケンス・エラーです。 | この関数は、実行時データの操作時に呼び出されました。 (すなわち、SQLParamData() または SQLPutData() 関数を使用するプロシージャー実行中に関数が呼び出されました。) |
| HY013 | 予期しない、メモリーのハンドル・エラーです。 | DB2 ODBC は、関数の実行または完了をサポートするのに必要なメモリーにアクセスすることができません。 |
| HY014 | これ以上ハンドルがありません。 | DB2 ODBC は、内部リソースが少ないため、ハンドルを割り振ることはできません。 |
| HY090 | ストリングまたはバッファーの長さが無効です。 | 引数 cbSqlStr は 1 より小さい値ですが、SQL_NTS と等しくありません。 |
注:
|
||
データベース管理システムは、準備の際に上記の診断メッセージをすべて報告するとは限りません。 したがって、SQLExecute() を呼び出す場合は、アプリケーションでも
これらの条件を取り扱えるようにしておく必要があります。
制約事項
準備されたステートメントが MERGE ステートメントの場合、ステートメント・テキストに FOR n ROWS 文節を組み込むことはできません。 結合する行数を指定するには、SQL_ATTR_PARAMSET_SIZE ステートメント属性とともに SQLSetStmtAttr() 関数を使用します。
例
SQLPrepare() を使用して SQL 文を作成するアプリケーションを示しています。 これと同じ SQL ステートメントを、その都度、
別のパラメーター値で 2 回実行します。 /******************************************************************/
/* Prepare a query and execute that query twice */
/* specifying a unique value for the parameter marker. */
/******************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlca.h>
#include "sqlcli1.h"
int main( )
{
SQLHENV hEnv = SQL_NULL_HENV;
SQLHDBC hDbc = SQL_NULL_HDBC;
SQLHSTMT hStmt = SQL_NULL_HSTMT;
SQLRETURN rc = SQL_SUCCESS;
SQLINTEGER RETCODE = 0;
char *pDSN = "STLEC1";
SWORD cbCursor;
SDWORD cbValue1;
SDWORD cbValue2;
char employee [30];
int salary = 0;
int param_salary = 30000;
char *stmt = "SELECT NAME, SALARY FROM EMPLOYEE WHERE SALARY > ?";
(void) printf ("**** Entering CLIP07.\n\n");
/*****************************************************************/
/* Allocate environment handle */
/*****************************************************************/
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
if (rc != SQL_SUCCESS)
goto dberror;
/*****************************************************************/
/* Allocate connection handle to DSN */
/*****************************************************************/
rc = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
if (rc != SQL_SUCCESS ) // Could not get a connect handle
goto dberror;
/*****************************************************************/
/* CONNECT TO data source (STLEC1) */
/*****************************************************************/
rc = SQLConnect(hDbc, // Connect handle
(SQLCHAR *) pDSN, // DSN
SQL_NTS, // DSN is nul-terminated
NULL, // Null UID
0 ,
NULL, // Null Auth string
0);
if (rc != SQL_SUCCESS ) // Connect failed
goto dberror;
/*****************************************************************/
/* Allocate statement handles */
/*****************************************************************/
rc = SQLAllocHandle (SQL_HANDLE_STMT, hDbc, &hStmt);
if (rc != SQL_SUCCESS)
goto dberror;
/*****************************************************************/
/* Prepare the query for multiple execution within current */
/* transaction. Note that query is collapsed when transaction */
/* is committed or rolled back. */
/*****************************************************************/
rc = SQLPrepare (hStmt,
(SQLCHAR *) stmt,
strlen(stmt));
if (rc != SQL_SUCCESS)
{
(void) printf ("**** PREPARE OF QUERY FAILED.\n");
goto dberror;
}
rc = SQLBindCol (hStmt, // bind employee name
1,
SQL_C_CHAR,
employee,
sizeof(employee),
&cbValue1);
if (rc != SQL_SUCCESS)
{
(void) printf ("**** BIND OF NAME FAILED.\n");
goto dberror;
}
rc = SQLBindCol (hStmt, // bind employee salary
2,
SQL_C_LONG,
&salary,
0,
&cbValue2);
if (rc != SQL_SUCCESS)
{
(void) printf ("**** BIND OF SALARY FAILED.\n");
goto dberror;
}
/*****************************************************************/
/* Bind parameter to replace '?' in query. This has an initial */
/* value of 30000. */
/*****************************************************************/
rc = SQLBindParameter (hStmt,
1,
SQL_PARAM_INPUT,
SQL_C_LONG,
SQL_INTEGER,
0,
0,
¶m_salary,
0,
NULL);
/*****************************************************************/
/* Execute prepared statement to generate answer set. */
/*****************************************************************/
rc = SQLExecute (hStmt);
if (rc != SQL_SUCCESS)
{
(void) printf ("**** EXECUTE OF QUERY FAILED.\n");
goto dberror;
}
/*****************************************************************/
/* Answer set is available -- Fetch rows and print employees */
/* and salary. */
/*****************************************************************/
(void) printf ("**** Employees whose salary exceeds %d follow.\n\n",
param_salary);
while ((rc = SQLFetch (hStmt)) == SQL_SUCCESS)
{
(void) printf ("**** Employee Name %s with salary %d.\n",
employee,
salary);
}
/*****************************************************************/
/* Close query --- note that query is still prepared. Then change*/
/* bound parameter value to 100000. Then re-execute query. */
/*****************************************************************/
rc = SQLCloseCursor(hStmt);
param_salary = 100000;
rc = SQLExecute (hStmt);
if (rc != SQL_SUCCESS)
{
(void) printf ("**** EXECUTE OF QUERY FAILED.\n");
goto dberror;
}
/*****************************************************************/
/* Answer set is available -- Fetch rows and print employees */
/* and salary. */
/*****************************************************************/
(void) printf ("**** Employees whose salary exceeds %d follow.\n\n",
param_salary);
while ((rc = SQLFetch (hStmt)) == SQL_SUCCESS)
{
(void) printf ("**** Employee Name %s with salary %d.\n",
employee,
salary);
}
/*****************************************************************/
/* Deallocate statement handles -- statement is no longer in a */
/* prepared state. */
/*****************************************************************/
rc = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
/*****************************************************************/
/* DISCONNECT from data source */
/*****************************************************************/
rc = SQLDisconnect(hDbc);
if (rc != SQL_SUCCESS)
goto dberror;
/*****************************************************************/
/* Deallocate connection handle */
/*****************************************************************/
rc = SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
if (rc != SQL_SUCCESS)
goto dberror;
/*****************************************************************/
/* Free environment handle */
/*****************************************************************/
rc = SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
if (rc == SQL_SUCCESS)
goto exit;
dberror:
RETCODE=12;
exit:
(void) printf ("**** Exiting CLIP07.\n\n");
return RETCODE;
}