ODBC API では、Transact-SQL ステートメントの繰り返し実行に関連する解析とコンパイルのオーバーヘッドを軽減する方法として、準備された実行が定義されています。 アプリケーションでは SQL ステートメントを保持する文字列を構築してから、そのステートメントを 2 段階に分けて実行します。 SQLPrepare 関数を 1 回呼び出して、 ステートメントを解析し、データベース エンジンによって実行プランにコンパイルします。 次に、準備された実行プランの実行ごとに SQLExecute を呼び出します。 この方法では、各実行にかかる解析とコンパイルのオーバーヘッドが抑制されます。 準備実行は、通常、同一のパラメーター化された SQL ステートメントを繰り返し実行するアプリケーションで使用されます。
ほとんどのデータベースでは、直接実行されるステートメントが実行のたびにコンパイルされるのに対し、準備実行されるステートメントは 1 回だけコンパイルされるので、準備実行は主に 4、5 回以上実行されるステートメントの場合は直接実行よりも高速になります。 準備実行では、SQL ステートメントが実行されるたびに、ドライバーはステートメント全体ではなく、実行プランの識別子とパラメーター値だけをデータ ソースに送信できるので、ネットワーク トラフィックも削減できます。
SQL Serverでは、SQLExecDirect から実行プランを検出して再利用するためのアルゴリズムが改善され、直接実行と準備された実行のパフォーマンスの違いが軽減されます。 そのため、直接実行されるステートメントでも、準備実行のパフォーマンス上の利点の一部を利用できるようになります。 詳細については、「 直接実行」を参照してください。
SQL Serverでは、準備された実行のネイティブ サポートも提供されます。 実行プランは SQLPrepare 上に構築され、 SQLExecute が呼び出されたときに後で実行されます。 SQL Serverは SQLPrepare で一時ストアド プロシージャをビルドする必要がないため、tempdb のシステム テーブルに余分なオーバーヘッドはありません。
パフォーマンス上の理由から、SQLExecute が呼び出されるか、メタプロパティ操作 (ODBC の SQLDescribeCol や SQLDescribeParam など) が実行されるまで、ステートメントの準備は延期されます。 これが既定の動作です。 準備されているステートメントのエラーは、ステートメントまたはメタプロパティ操作が実行されるまでわかりません。 SQL SERVER NATIVE CLIENT ODBC ドライバー固有のステートメント属性SQL_SOPT_SS_DEFER_PREPAREを SQL_DP_OFF に設定すると、この既定の動作を無効にすることができます。
遅延準備の場合、SQLExecute を呼び出す前に SQLDescribeCol または SQLDescribeParam を呼び出すと、サーバーへの余分なラウンドトリップが生成されます。 SQLDescribeCol では、ドライバーはクエリから WHERE 句を削除し、SET FMTONLY ON を使用してサーバーに送信して、クエリによって返される最初の結果セット内の列の説明を取得します。 SQLDescribeParam では、ドライバーはサーバーを呼び出して、クエリ内のパラメーター マーカーによって参照される式または列の説明を取得します。 この方法には、サブクエリのパラメーターを解決することができないなど、いくつか制限事項もあります。
SQL SERVER NATIVE CLIENT ODBC ドライバーで SQLPrepare を過剰に使用すると、特に以前のバージョンのSQL Serverに接続している場合、パフォーマンスが低下します。 準備実行は、1 回しか実行されないステートメントには使用しないでください。 準備実行では、クライアントからサーバーへのネットワーク上のやり取りを余分に実行する必要があるため、ステートメントを 1 回しか実行しない場合は直接実行よりも時間がかかります。 以前のバージョンのSQL Serverでは、一時ストアド プロシージャも生成されます。
SQL Server では、準備されたステートメントを使用して一時オブジェクトを作成することはできません。
一部の初期の ODBC アプリケーションでは、SQLBindParameter が使用されるたびに SQLPrepare を使用していました。 SQLBindParameter では SQLPrepare を使用する必要はありません。 SQLExecDirect で使用できます。 たとえば、SQLBindParameter で SQLExecDirect を使用して、1 回だけ実行されるストアド プロシージャから戻りコードまたは出力パラメーターを取得します。 同じステートメントが複数回実行されない限り、SQLBindParameter で SQLPrepare を使用しないでください。