次の方法で共有


ODBC テーブル値パラメーターの使用

このトピックでは、ODBC でテーブル値パラメーターを使用する主なユーザー シナリオについて説明します。

  • 複数行のバッファーに完全にバインドされるテーブル値パラメーター (すべての値をメモリ内に保持した TVP としてデータを送信する)

  • 行のストリーミングを使用するテーブル値パラメーター (実行時のデータを使用する TVP としてデータを送信する)

  • システム カタログからテーブル値パラメーターのメタデータを取得

  • 準備されたステートメント用にテーブル値パラメーターのメタデータを取得

複数行のバッファーに完全にバインドされるテーブル値パラメーター (すべての値をメモリ内に保持した TVP としてデータを送信する)

複数行のバッファーに完全にバインドされる形式で使用する場合、すべてのパラメーター値はメモリ内から使用できます。 このような形式は OLTP トランザクションなどでは一般的に行われ、テーブル値パラメーターを 1 つのストアド プロシージャにパッケージ化できます。 テーブル値パラメーターを使用しないと、複雑な複数のステートメントで構成されるバッチを動的に生成し、サーバーを複数回呼び出すことになります。

テーブル値パラメーター自体は他のパラメーターと共に、SQLBindParameter を使用してバインドされます。 すべてのパラメーターがバインドされたら、アプリケーションでは、各テーブル値パラメーターのパラメーター フォーカスの属性 SQL_SOPT_SS_PARAM_FOCUS を設定し、テーブル値パラメーターの列に対して SQLBindParameter を呼び出します。

テーブル値パラメーターのサーバー型は、SQL Server 固有の新しい型 SQL_SS_TABLE です。 SQL_SS_TABLE の C データ型へのバインドは、常に SQL_C_DEFAULT にする必要があります。 テーブル値パラメーターにバインドされたパラメーターについては、データが転送されません。このパラメーターは、テーブルのメタデータを渡し、テーブル値パラメーターを構成する列にデータを渡す方法を制御するために使用されます。

テーブル値パラメーターの長さには、サーバーに送信される行数が設定されます。 テーブル値パラメーターの SQLBindParameter の ColumnSize パラメーターでは、送信できる最大行数を指定します。この値は、列バッファーの配列のサイズです。ParameterValuePtr は、SQLBindParameter のテーブル値パラメーター用のパラメーター バッファーです。ParameterValuePtr およびこれと関連する BufferLength は、必要に応じてテーブル値パラメーターの型名を渡すために使用されます。 型名は、ストアド プロシージャの呼び出しには必要ありませんが、SQL ステートメントには必要です。

テーブル値パラメーターの型名を SQLBindParameter の呼び出しで指定する場合、ANSI アプリケーションとしてビルドされているアプリケーションであっても、常に Unicode 値として指定する必要があります。 SQLSetDescField を使用してテーブル値パラメーターの型名を指定する場合は、アプリケーションのビルド方法に準拠したリテラルを使用できます。 ODBC ドライバー マネージャーで、必要な Unicode 変換を実行します。

テーブル値パラメーターのメタデータおよびテーブル値パラメーターの列は、SQLGetDescRecSQLSetDescRecSQLGetDescField、および SQLSetDescField を使用して、個別に明示的に操作できます。 ただし、通常は SQLBindParameter をオーバーロードする方が便利で、ほとんどの場合に明示的な記述子のアクセスが必要ありません。 この方法は、テーブル値パラメーターの影響を受ける記述子フィールドがやや異なる点を除いて、他のデータ型の SQLBindParameter の定義と一貫性があります。

アプリケーションでは、場合によっては、動的な SQL を含むテーブル値パラメーターを使用して、テーブル値パラメーターの型名を指定する必要があります。 このような場合に、テーブル値パラメーターが接続の現在の既定のスキーマで定義されていないときは、SQLSetDescField を使用して、SQL_CA_SS_TYPE_CATALOG_NAME および SQL_CA_SS_TYPE_SCHEMA_NAME を設定する必要があります。 テーブル型の定義とテーブル値パラメーターは同じデータベースに存在する必要があるため、アプリケーションでテーブル値パラメーターを使用する場合は、SQL_CA_SS_TYPE_CATALOG_NAME を設定しないでください。 設定すると、SQLSetDescField でエラーが報告されます。

このシナリオのサンプル コードは、CodePlex で入手できるサンプル アプリケーションの demo_fixed_table-valued parameter_binding プロシージャに含まれています。詳細については、「SQL Server データベース エンジン サンプル」を参照してください。

行のストリーミングを使用するテーブル値パラメーター (実行時のデータを使用する TVP としてデータを送信する)

このシナリオでは、要求に応じてアプリケーションからドライバーに行が渡され、サーバーにストリーム送信されます。 これにより、すべての行をメモリ内にバッファリングする必要がなくなります。 これは、一括挿入や一括更新のシナリオの代表的な例です。 テーブル値パラメーターは、パフォーマンスの点ではパラメーター配列と一括コピーとの間に位置します。 つまり、テーブル値パラメーターは、パラメーター配列と同程度にプログラミングが容易ですが、サーバー側の柔軟性が増します。

テーブル値パラメーターとその列は、前の「複数行のバッファーに完全にバインドされるテーブル値パラメーター」で説明したとおりにバインドされますが、テーブル値パラメーター自体の長さのインジケーターは、SQL_DATA_AT_EXEC に設定されます。 ドライバーは、実行時データ パラメーターの通常の方法 (SQL_NEED_DATA を返す方法) で、SQLExecute または SQLExecuteDirect に応答します。 ドライバーでテーブル値パラメーターのデータを受け取る準備ができたら、SQLParamDataSQLBindParameter の ParameterValuePtr の値を返します。

アプリケーションでは、テーブル値パラメーターに SQLPutData を使用して、テーブル値パラメーターを構成する列のデータが利用できるかどうかを示します。 テーブル値パラメーターに対して SQLPutData が呼び出されるとき、DataPtr は常に NULL である必要があり、StrLen_or_Ind は 0 またはテーブル値パラメーターのバッファーに指定された配列のサイズ (SQLBindParameter の ColumnSize パラメーター) の数値以下である必要があります。 0 はテーブル値パラメーターの行がなくなったことを示すため、ドライバーはプロシージャの次の実パラメーターの処理に進みます。 StrLen_or_Ind が 0 ではない場合、ドライバーは、テーブル値パラメーターにバインドされていないパラメーターと同じ方法で、テーブル値パラメーターを構成する列を処理します。つまり、テーブル値パラメーターの各列で、その実際のデータ長 (SQL_NULL_DATA) を指定するか、長さまたはインジケーターのバッファーを使用して実行時データを指定することができます。 文字値またはバイナリ値が個別に渡される場合、通常どおり SQLPutData を繰り返し呼び出すことで、テーブル値パラメーターの列の値を渡すことができます。

テーブル値パラメーターのすべての列が処理されたら、ドライバーはテーブル値パラメーターに戻り、テーブル値パラメーターのデータの次の行を処理します。 したがって、実行時データのテーブル値パラメーターの場合、バインドされたパラメーターを順番にスキャンする通常の方法には従いません。 バインドされたテーブル値パラメーターは、StrLen_Or_IndPtr が 0 の状態で SQLPutData が呼び出されるまでポーリングされます。0 の状態で呼び出された時点で、ドライバーはテーブル値パラメーターの列をスキップし、ストアド プロシージャの次の実パラメーターに移動します。 SQLPutData から 1 以上のインジケーター値を渡すと、ドライバーはバインドされたすべての行と列の値を取得するまで、テーブル値パラメーターの列と行を順番に処理します。 その後、ドライバーはテーブル値パラメーターに戻ります。 SQLParamData からテーブル値パラメーターのトークンを取得してから、テーブル値パラメーターの SQLPutData(hstmt, NULL, n) を呼び出すまでの間に、アプリケーションでは、サーバーに渡す次の行に、テーブル値パラメーターを構成する列のデータおよびインジケーター バッファーの内容を設定する必要があります。

このシナリオのサンプル コードは、CodePlex で入手できるサンプル アプリケーションの demo_variable_table-valued parameter_binding ルーチンに含まれています。詳細については、「SQL Server データベース エンジン サンプル」を参照してください。

システム カタログからテーブル値パラメーターのメタデータを取得

アプリケーションからテーブル値パラメーターをパラメーターに含むプロシージャに対して SQLProcedureColumns を呼び出すと、DATA_TYPE は SQL_SS_TABLE として返され、TYPE_NAME はテーブル値パラメーターのテーブル型の名前です。 新たに 2 つの列が、SQLProcedureColumns によって返される結果セットに追加されます。1 つは SS_TYPE_CATALOG_NAME で、テーブル値パラメーターのテーブル型が定義されているカタログの名前を返します。もう 1 つは SS_TYPE_SCHEMA_NAME で、テーブル値パラメーターのテーブル型が定義されているスキーマの名前を返します。 SS_TYPE_CATALOG_NAME および SS_TYPE_SCHEMA_NAME は、ODBC 仕様に準拠して、以前のバージョンの SQL Server で追加されたドライバー固有のすべての列の前、かつ ODBC 自体によって指定されるすべての列の後に作成されます。

新しい列は、テーブル値パラメーター用だけでなく、CLR ユーザー定義型パラメーター用にも作成されます。 UDT パラメーターの既存のスキーマ列とカタログ列も依然として作成されますが、共通のスキーマ列とカタログ列を必要とするデータ型にもそれらの列を含めておくと、今後アプリケーション開発が簡単になります (XML スキーマ コレクションは多少異なり、この変更には含まれていないことに注意してください)。

アプリケーションでは SQLTables を使用して、永続的なテーブル、システム テーブル、およびビューと同じ方法で、テーブル型の名前を決定します。 アプリケーションでテーブル値パラメーターに関連付けられたテーブル型を識別できるように、新しいテーブル型として TABLE TYPE が導入されました。 テーブル型と通常のテーブルでは、異なる名前空間を使用します。 つまり、テーブル型と実際のテーブルに、同じ名前を使用できます。 これに対処するために、新しいステートメント属性として SQL_SOPT_SS_NAME_SCOPE が導入されました。 この属性では、テーブル名をパラメーターとして受け取る SQLTables やその他のカタログ関数で、テーブル名を実際のテーブルの名前として解釈するか、テーブル型の名前として解釈するかを指定します。

アプリケーションでは、SQLColumns を使用して、永続的なテーブルと同じ方法でテーブル型の列を決定しますが、まず SQL_SOPT_SS_NAME_SCOPE を指定して、実際のテーブルではなくテーブル型に対して操作していることを示す必要があります。テーブル型では SQLPrimaryKeys も使用でき、この場合も SQL_SOPT_SS_NAME_SCOPE を使用します。

このシナリオのサンプル コードは、CodePlex で入手できるサンプル アプリケーションの demo_metadata_from_catalog_APIs ルーチンに含まれています。詳細については、「SQL Server データベース エンジン サンプル」を参照してください。

準備されたステートメント用にテーブル値パラメーターのメタデータを取得

このシナリオでは、アプリケーションで SQLNumParameters および SQLDescribeParam を使用して、テーブル値パラメーターのメタデータを取得します。

IPD フィールド SQL_CA_SS_TYPE_NAME は、テーブル値パラメーターの型名を取得するために使用されます。 IPD フィールド SQL_CA_SS_TYPE_SCHEMA_NAME と SQL_CA_SS_TYPE_CATALOG_NAME は、それぞれスキーマとカタログを取得するために使用されます。

テーブル型の定義とテーブル値パラメーターは同じデータベースに存在する必要があります。テーブル値パラメーターを使用しているときに、アプリケーションで SQL_CA_SS_TYPE_CATALOG_NAME を設定すると、SQLSetDescField でエラーが報告されます。

SQL_CA_SS_TYPE_CATALOG_NAME および SQL_CA_SS_TYPE_SCHEMA_NAME を使用すると、CLR ユーザー定義型パラメーターに関連付けられたカタログとスキーマも取得できます。 SQL_CA_SS_TYPE_CATALOG_NAME および SQL_CA_SS_TYPE_SCHEMA_NAME は、CLR UDT 型の既存の型固有のカタログ スキーマの属性の代わりに使用します。

このシナリオでは、SQLDescribeParam によってテーブル値パラメーター列の列のメタデータが返されないため、アプリケーションで SQLColumns を使用して、テーブル値パラメーター列のメタデータも取得します。

このユース ケースのサンプル コードは、CodePlex で入手できるサンプル アプリケーションの demo_metadata_from_prepared_statement ルーチンに含まれています。詳細については、「SQL Server データベース エンジン サンプル」を参照してください。

変更履歴

変更内容

サンプルへのリンクを更新しました。