次の方法で共有


結果データのフェッチ

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)

ODBC アプリケーションでは、結果データのフェッチを 3 つの方法で実行できます。

最初のオプションは SQLBindCol に基づいています。 結果セットをフェッチする前に、アプリケーションは SQLBindCol を使用して、結果セット内の各列をプログラム変数にバインドします。 列がバインドされると、ドライバーは、アプリケーションが SQLFetch または SQLFetchScroll を呼び出すたびに、現在の行のデータを結果セット列にバインドされた変数に転送します。 結果セット列のデータ型とプログラム変数のデータ型が異なる場合、ドライバーによってデータ変換が処理されます。 アプリケーションに 1 より大きい値SQL_ATTR_ROW_ARRAY_SIZE設定されている場合は、結果列を変数の配列にバインドできます。これはすべて、 SQLFetchScroll の各呼び出しで入力されます。

2 番目のオプションは SQLGetData に基づいています。 アプリケーションでは、 SQLBindCol を使用して結果セット列をプログラム変数にバインドしません。 SQLFetch を呼び出すたびに、アプリケーションは結果セット内の各列に対して SQLGetData を 1 回呼び出します。 SQLGetData は、特定の結果セット列から特定のプログラム変数にデータを転送するようにドライバーに指示し、列と変数のデータ型を指定します。 そのため、結果列のデータ型とプログラム変数のデータ型が異なる場合は、ドライバーでデータを変換できます。 通常、テキストntextおよびイメージ の列は大きすぎてプログラム変数に収まりませんが、引き続き SQLGetData を使用して取得できます。 結果列の textntext、または image データがプログラム変数より大きい場合、 SQLGetData は SQL_SUCCESS_WITH_INFOおよび SQLSTATE 01004 (文字列データ、右切り捨て) を返します。 SQLGetData を連続して呼び出すと、テキストまたはイメージ データの連続するチャンクが返されます。 データの末尾に達すると、 SQLGetData はSQL_SUCCESSを返します。 SQL_ATTR_ROW_ARRAY_SIZE に 1 よりも大きい値を指定すると、フェッチのたびに行セットが返されます。 SQLGetData を使用する前に、まず SQLSetPos を使用して、行セット内の特定の行を現在の行として指定する必要があります。

3 番目のオプションは、 SQLBindColSQLGetData の組み合わせを使用することです。 たとえば、アプリケーションは結果セットの最初の 10 列をバインドし、フェッチのたびに SQLGetData を 3 回呼び出して、3 つの非連結列からデータを取得できます。 これは通常、結果セットに 1 つ以上の テキスト 列または 画像 列が含まれている場合に使用されます。

結果セットに設定されているカーソル オプションに応じて、アプリケーションで SQLFetchScroll のスクロール オプションを使用して結果セットをスクロールすることもできます。

SQLBindCol を使用して結果セット列をプログラム変数にバインドすると、SQLBindCol によって ODBC ドライバーにメモリが割り当てられるため、コストがかかります。 結果列を変数にバインドする場合、SQLFreeHandle を呼び出してステートメント ハンドルを解放するか、fOption を SQL_UNBINDに設定して SQLFreeStmt を呼び出すまで、そのバインドは有効なままになります。 バインドは、ステートメントが完了しても自動的には元に戻りません。

このロジックにより、異なるパラメーターを指定して同じ SELECT ステートメントを何度も実行することで、効率を上げることができます。 結果セットは同じ構造を保持するため、結果セットを 1 回バインドし、すべての SELECT ステートメントを処理してから、最後の実行後に fOption を SQL_UNBIND に設定して SQLFreeStmt を呼び出すことができます。 SQLBindCol を呼び出して結果セット内の列をバインドしないでください。前のバインディングを解放するには、fOption を SQL_UNBIND に設定して SQLFreeStmt を最初に呼び出す必要があります。

SQLBindCol を使用する場合は、行方向または列方向のバインドを実行できます。 行方向のバインドの方が、列方向のバインドよりも処理がやや高速になります。

SQLGetData を使用すると、SQLBindCol を使用して結果セット列をバインドする代わりに、列ごとにデータを取得できます。 結果セットに含まれる行数が少ない場合は、SQLBindCol の代わりに SQLGetData を使用する方が高速です。それ以外の場合は、SQLBindCol によって最適なパフォーマンスが得られます。 常に同じ変数セットにデータを配置しない場合は、常に再バインドする代わりに SQLGetData を使用する必要があります。 SQLGetData は、すべての列が SQLBindCol でバインドされた後、選択リスト内の列でのみ使用できます。 この列は、 SQLGetData を既に使用している列の後にも表示する必要があります。

SQLGetDataSQLBindColSQLBindParameter などのプログラム変数との間でのデータの移動を処理する ODBC 関数は、暗黙的なデータ型変換をサポートします。 たとえば、整数列を文字列プログラム変数にバインドするアプリケーションでは、プログラム変数にデータを格納する前に、ドライバーが自動的にそのデータを整数から文字に変換します。

アプリケーションでのデータ変換は最小限に抑える必要があります。 列やパラメーターは、アプリケーションでの処理にデータ変換が必要な場合を除き、同じデータ型のプログラム変数にバインドする必要があります。 ただし、あるデータ型から別のデータ型に変換する必要がある場合は、アプリケーションでのデータ変換よりもドライバーによるデータ変換の方が効率的です。 SQL Server Native Client ODBC ドライバーは、通常、ネットワーク バッファーからアプリケーションの変数に直接データを転送するだけです。 データ変換を行うようにドライバーに要求すると、ドライバーはデータをバッファーに格納し、CPU サイクルを使用してデータを変換します。

プログラム変数は、 テキストntext画像 データを除き、列から転送されたデータを保持するのに十分な大きさにする必要があります。 結果セットのデータを取得してそのデータを変数に格納するときに、その変数が小さすぎてデータを保持できない場合、ドライバーは警告を生成します。 その結果、ドライバーでは警告メッセージ用のメモリを割り当て、ドライバーとアプリケーションの両方で、警告メッセージの処理やエラーの処理に CPU サイクルが必要になります。 アプリケーションでは、取得するデータを保持するのに十分なサイズの変数を割り当てるか、選択リストで SUBSTRING 関数を使用して結果セット内の列のサイズを小さくする必要があります。

SQL_C_DEFAULT を使用して C 変数のデータ型を指定する場合は注意が必要です。 SQL_C_DEFAULT は、C 変数のデータ型と、列やパラメーターの SQL データ型を一致させることを指定します。 ntext、nchar、または nvarcharにSQL_C_DEFAULTが指定されている場合、Unicode データがアプリケーションに返されます。 そのため、アプリケーションが Unicode データを処理するようにコーディングされていないと、さまざまな問題が発生する可能性があります。 uniqueidentifier (SQL_GUID) データ型でも同じ種類の問題が発生する可能性があります。

textntext、および image データは通常、大きすぎて 1 つのプログラム変数に収まらないため、通常は SQLBindCol ではなく SQLGetData で処理されます。 サーバー カーソルを使用する場合、SQL Server Native Client ODBC ドライバーは、行のフェッチ時に非連結テキストntext、またはイメージ列のデータを送信しないように最適化されます。 テキストntext、またはイメージ データは、アプリケーションが列に対して SQLGetData を発行するまで、実際にはサーバーから取得されません。

この最適化をアプリケーションに適用すると、ユーザーがカーソルを上下にスクロールしている間に テキストntext、または 画像 データが表示されなくなります。 ユーザーが行を選択すると、アプリケーションは SQLGetData を呼び出して、 テキストntext、または イメージ データを取得できます。 これにより、ユーザーが選択しない行の テキストntext、または 画像 データの送信が保存され、非常に大量のデータの送信を保存できます。

参照

結果の処理 (ODBC)