準備実行 ODBC
準備された実行は、ステートメントを複数回実行する効率的な方法です。 ステートメントは、最初にコンパイルされるか、アクセス プランに準備されます。 その後、アクセス プランは後で 1 回以上実行されます。 アクセス プランの詳細については、「 SQL ステートメントの処理」を参照してください。
準備実行は、同じパラメーター化された SQL ステートメントを繰り返し実行するために、バーティカル アプリケーションおよびカスタム アプリケーションで一般的に使用されます。 たとえば、次のコードは、さまざまな部分の価格を更新するステートメントを準備します。 その後、毎回異なるパラメーター値でステートメントを複数回実行します。
SQLREAL Price;
SQLUINTEGER PartID;
SQLINTEGER PartIDInd = 0, PriceInd = 0;
// Prepare a statement to update salaries in the Employees table.
SQLPrepare(hstmt, "UPDATE Parts SET Price = ? WHERE PartID = ?", SQL_NTS);
// Bind Price to the parameter for the Price column and PartID to
// the parameter for the PartID column.
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL, 7, 0,
&Price, 0, &PriceInd);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 10, 0,
&PartID, 0, &PartIDInd);
// Repeatedly execute the statement.
while (GetPrice(&PartID, &Price)) {
SQLExecute(hstmt);
}
直接実行されるステートメントが実行のたびにコンパイルされるのに対し、準備実行されるステートメントは 1 回だけコンパイルされるので、準備実行は主に 1 回以上実行されるステートメントの場合は直接実行よりも高速になります。 データ ソースがアクセス プラン識別子をサポートしている場合、ドライバーは SQL ステートメント全体ではなく、ステートメントが実行されるたびにアクセス プラン識別子をデータ ソースに送信できるため、準備実行によってネットワーク トラフィックも削減できます。
アプリケーションは、ステートメントの準備後と実行前に、結果セットのメタデータを取得できます。 ただし、準備された実行されていないステートメントのメタデータを返すと、一部のドライバーにはコストがかかるため、可能な場合は相互運用可能なアプリケーションで回避する必要があります。 詳細については、「メタデータの結果セット」を参照してください。
準備実行は、1 回しか実行されないステートメントには使用しないでください。 このようなステートメントの場合、ODBC 関数呼び出しを追加する必要があるため、直接実行よりも若干遅くなります。
重要
SQLEndTran を明示的に呼び出すか、自動コミット モードで作業することによって、トランザクションをコミットまたはロールバックすると、一部のデータ ソースは接続上のすべてのステートメントのアクセス プランを削除します。 詳細については、SQLGetInfo 関数の説明の SQL_CURSOR_COMMIT_BEHAVIOR オプションと SQL_CURSOR_ROLLBACK_BEHAVIOR オプションを参照してください。
ステートメントを準備して実行するために、アプリケーションは次の手順を実行します。
SQLPrepare を呼び出し、SQL ステートメントを含む文字列を渡します。
任意のパラメーターの値を設定します。 パラメーターは、実際には、ステートメントの準備の前または準備後に設定できます。 詳細については、このセクションの後にある「ステートメント パラメーター」を参照してください。
SQLExecute を呼び出し、データのフェッチなど、必要な追加処理を実行します。
必要に応じて、ステップ 2 と 3 を繰り返します。
SQLPrepare が呼び出されると、ドライバーは次のようになります。
ステートメントを解析せずにデータ ソースの SQL 文法を使用するように SQL ステートメントを変更します。 これには、ODBC のエスケープ シーケンスで説明されているエスケープ シーケンスの置き換えも含まれます。 アプリケーションは、
SQLNativeSql を呼び出すことによって、変更された形式の SQL ステートメントを取得できます。 SQL_ATTR_NOSCAN ステートメント属性が設定されている場合、エスケープ シーケンスは置き換えされません。準備用のステートメントをデータ ソースに送信します。
後で実行するために返されたアクセス プラン識別子を格納するか (準備が成功した場合)、またはエラー (準備が失敗した場合) を返します。 エラーには、SQLSTATE 42000 (構文エラーまたはアクセス違反) などの構文エラーや、SQLSTATE 42S02 (ベース テーブルまたはビューが見つからない) などのセマンティック エラーが含まれます。
Note
一部のドライバーは、この時点ではエラーを返しませんが、代わりにステートメントが実行されたとき、またはカタログ関数が呼び出されたときにエラーを返します。 したがって、SQLPrepare は実際に失敗した場合に成功したように見える場合があります。
SQLExecute が呼び出されると、ドライバーは次のようになります。
現在のパラメーター値を取得し、必要に応じて変換します。 詳細については、このセクションの後にある「ステートメント パラメーター」を参照してください。
アクセス プラン識別子と変換されたパラメーター値をデータ ソースに送信します。
エラーが返されます。 これらは通常、SQLSTATE 24000 (無効なカーソル状態) などの実行時エラーです。 ただし、一部のドライバーは、この時点で構文エラーとセマンティック エラーを返します。
データ ソースがステートメントの準備をサポートしていない場合、ドライバーは可能な限りそれをエミュレートする必要があります。 たとえば、SQLPrepare が呼び出されたときにドライバーが何も実行せず、SQLExecute が呼び出されたときにステートメントを直接実行する場合があります。
データ ソースが実行なしで構文チェックをサポートしている場合、ドライバーは、SQLPrepare が呼び出されたときに確認するためのステートメントを送信し、SQLExecute が呼び出されたときには実行するステートメントを送信する可能性があります。
ドライバーは、ステートメントの準備をエミュレートできない場合は、SQLPrepare が呼び出されたときにステートメントを格納し、SQLExecute が呼び出されたときに実行のために送信します。
エミュレートされたステートメントの準備は完璧ではないため、SQLExecute は SQLPrepare によって通常返されるすべてのエラーを返すことができます。