準備実行 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 オプションを参照してください。

ステートメントを準備して実行するために、アプリケーションは次の手順を実行します。

  1. SQLPrepare を呼び出し、SQL ステートメントを含む文字列を渡します。

  2. 任意のパラメーターの値を設定します。 パラメーターは、実際には、ステートメントの準備の前または準備後に設定できます。 詳細については、このセクションの後にある「ステートメント パラメーター」を参照してください。

  3. SQLExecute を呼び出し、データのフェッチなど、必要な追加処理を実行します。

  4. 必要に応じて、ステップ 2 と 3 を繰り返します。

  5. SQLPrepare が呼び出されると、ドライバーは次のようになります。

    • ステートメントを解析せずにデータ ソースの SQL 文法を使用するように SQL ステートメントを変更します。 これには、ODBC のエスケープ シーケンスで説明されているエスケープ シーケンスの置き換えも含まれます。 アプリケーションは、SQLNativeSql を呼び出すことによって、変更された形式の SQL ステートメントを取得できます。 SQL_ATTR_NOSCAN ステートメント属性が設定されている場合、エスケープ シーケンスは置き換えされません。

    • 準備用のステートメントをデータ ソースに送信します。

    • 後で実行するために返されたアクセス プラン識別子を格納するか (準備が成功した場合)、またはエラー (準備が失敗した場合) を返します。 エラーには、SQLSTATE 42000 (構文エラーまたはアクセス違反) などの構文エラーや、SQLSTATE 42S02 (ベース テーブルまたはビューが見つからない) などのセマンティック エラーが含まれます。

      Note

      一部のドライバーは、この時点ではエラーを返しませんが、代わりにステートメントが実行されたとき、またはカタログ関数が呼び出されたときにエラーを返します。 したがって、SQLPrepare は実際に失敗した場合に成功したように見える場合があります。

  6. SQLExecute が呼び出されると、ドライバーは次のようになります。

    • 現在のパラメーター値を取得し、必要に応じて変換します。 詳細については、このセクションの後にある「ステートメント パラメーター」を参照してください。

    • アクセス プラン識別子と変換されたパラメーター値をデータ ソースに送信します。

    • エラーが返されます。 これらは通常、SQLSTATE 24000 (無効なカーソル状態) などの実行時エラーです。 ただし、一部のドライバーは、この時点で構文エラーとセマンティック エラーを返します。

データ ソースがステートメントの準備をサポートしていない場合、ドライバーは可能な限りそれをエミュレートする必要があります。 たとえば、SQLPrepare が呼び出されたときにドライバーが何も実行せず、SQLExecute が呼び出されたときにステートメントを直接実行する場合があります。

データ ソースが実行なしで構文チェックをサポートしている場合、ドライバーは、SQLPrepare が呼び出されたときに確認するためのステートメントを送信し、SQLExecute が呼び出されたときには実行するステートメントを送信する可能性があります。

ドライバーは、ステートメントの準備をエミュレートできない場合は、SQLPrepare が呼び出されたときにステートメントを格納し、SQLExecute が呼び出されたときに実行のために送信します。

エミュレートされたステートメントの準備は完璧ではないため、SQLExecuteSQLPrepare によって通常返されるすべてのエラーを返すことができます。