テーブル値パラメータおよび列の値のバインドとデータ転送

テーブル値パラメータは、他のパラメータと同様、サーバーに渡す前にバインドする必要があります。アプリケーションでは、他のパラメータと同じように、SQLBindParameter、または同等の SQLSetDescFieldSQLSetDescRec を呼び出すことにより、テーブル値パラメータをバインドします。テーブル値パラメータ用のサーバーのデータ型は SQL_SS_TABLE です。C 型は SQL_C_DEFAULT または SQL_C_BINARY として指定できます。

SQL Server 2008 では、入力のテーブル値パラメータのみがサポートされています。そのため、SQL_DESC_PARAMETER_TYPE に SQL_PARAM_INPUT 以外の値を設定しようとすると、SQLSTATE = HY105 の SQL_ERROR が発生し、"パラメータの型が無効です。" というメッセージが返されます。

属性 SQL_CA_SS_COL_HAS_DEFAULT_VALUE を使用すると、テーブル値パラメータのすべての列に既定値を割り当てることができます。ただし、SQLBindParameter で StrLen_or_IndPtr に SQL_DEFAULT_PARAM を使用しても、テーブル値パラメータの各列の値に既定値を割り当てることはできません。また SQLBindParameter で StrLen_or_IndPtr に SQL_DEFAULT_PARAM を使用しても、テーブル値パラメータ全体に既定値を設定することはできません。これらの規則に従わない場合、SQLExecute または SQLExecDirect が SQL_ERROR を返し、"パラメータ <p> に既定のパラメータを使用できません" というメッセージを含む、SQLSTATE=07S01 の診断レコードが生成されます。<p> は、クエリ ステートメントにおける TVP の序数です。

テーブル値パラメータをバインドしたら、アプリケーションでは、次に、テーブル値パラメータの各列をバインドする必要があります。これを行うには、アプリケーションで、まず SQLSetStmtAttr を呼び出し、テーブル値パラメータの序数に SQL_SOPT_SS_PARAM_FOCUS を設定します。次に、SQLBindParameterSQLSetDescRec、および SQLSetDescField の各ルーチンを呼び出して、テーブル値パラメータの列をバインドします。SQL_SOPT_SS_PARAM_FOCUS を 0 に設定すると、標準の最上位パラメータを使用する際に SQLBindParameterSQLSetDescRecSQLSetDescField と同じ効果が復元されます。

テーブル値パラメータ自体の実際のデータは送受信されませんが、テーブル値パラメータを構成する各列のデータは送受信されます。テーブル値パラメータは擬似列なので、SQLBindParameter のパラメータは、次のように、他のデータ型とは異なる属性を参照するために使用されます。

パラメータ

テーブル値パラメータ以外のパラメータ (列など) に関連する属性

テーブル値パラメータに関連する属性

InputOutputType

IPD の SQL_DESC_PARAMETER_TYPE。

テーブル値パラメータの列の場合、これはテーブル値パラメータ自体の設定と同じである必要があります。

IPD の SQL_DESC_PARAMETER_TYPE。

これは SQL_PARAM_INPUT である必要があります。

ValueType

APD の SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

APD の SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

これは SQL_C_DEFAULT または SQL_C_BINARY である必要があります。

ParameterType

IPD の SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

IPD の SQL_DESC_TYPE、SQL_DESC_CONCISE_TYPE。

これは SQL_SS_TABLE である必要があります。

ColumnSize

IPD の SQL_DESC_LENGTH または SQL_DESC_PRECISION。

これは ParameterType の値によって異なります。

SQL_DESC_ARRAY_SIZE。

テーブル値パラメータにフォーカスが設定されている場合は SQL_ATTR_PARAM_SET_SIZE を使用して設定することもできます。

テーブル値パラメータの場合、これはテーブル値パラメータの列バッファ内の行数です。

DecimalDigits

IPD の SQL_DESC_PRECISION または SQL_DESC_SCALE。

使用しません。これは 0 である必要があります。

このパラメータが 0 でない場合、SQLBindParameter は SQL_ERROR を返し、"有効桁数または小数点以下桁数が無効です" というメッセージを含む SQLSTATE= HY104 の診断レコードが生成されます。

ParameterValuePtr

APD の SQL_DESC_DATA_PTR。

SQL_CA_SS_TYPE_NAME。

これは、ストアド プロシージャの呼び出しでは省略可能で、不要の場合は NULL を指定できます。プロシージャの呼び出し以外の SQL ステートメントでは、指定する必要があります。

このパラメータは、可変の行バインドの使用時にアプリケーションがテーブル値パラメータを特定するための一意の値としても機能します。詳細については、「テーブル値パラメータの可変の行バインド」を参照してください。

テーブル値パラメータの型名を SQLBindParameter の呼び出しで指定する場合、ANSI アプリケーションとしてビルドされているアプリケーションであっても、Unicode 値として指定する必要があります。パラメータ StrLen_or_IndPtr に使用する値は、SQL_NTS であるか、または名前の文字列長に sizeof(WCHAR) を掛けた値である必要があります。

BufferLength

APD の SQL_DESC_OCTET_LENGTH。

テーブル値パラメータの型名の長さ (バイト単位)。

型名が NULL 終端の場合は SQL_NTS に、テーブル値パラメータの型名が不要の場合は 0 になります。

StrLen_or_IndPtr

APD の SQL_DESC_OCTET_LENGTH_PTR。

APD の SQL_DESC_OCTET_LENGTH_PTR。

テーブル値パラメータの場合、これはデータ長ではなく行数です。

テーブル値パラメータでは、固定の行バインドと可変の行バインドという 2 つのデータ転送モードがサポートされています。

テーブル値パラメータの固定の行バインド

固定の行バインドの場合、アプリケーションでは、使用可能なすべての入力列の値に対して十分な大きさのバッファ (バッファ配列) を割り当てます。このアプリケーションによって次の処理が行われます。

  1. SQLBindParameterSQLSetDescRec、または SQLSetDescField の呼び出しを使用して、すべてのパラメータをバインドします。

    1. SQL_DESC_ARRAY_SIZE に各テーブル値パラメータの転送可能な最大行数を設定します。これは、SQLBindParameter の呼び出しで行うことができます。
  2. SQLSetStmtAttr を呼び出して、SQL_SOPT_SS_PARAM_FOCUS に各テーブル値パラメータの序数を設定します。

    1. テーブル値パラメータごとに、SQLBindParameterSQLSetDescRec、または SQLSetDescField の呼び出しを使用して、テーブル値パラメータの列をバインドします。

    2. 既定値を指定するテーブル値パラメータの列ごとに、SQLSetDescField を呼び出して SQL_CA_SS_COL_HAS_DEFAULT_VALUE に 1 を設定します。

  3. SQLSetStmtAttr を呼び出して SQL_SOPT_SS_PARAM_FOCUS に 0 を設定します。これは、SQLExecute または SQLExecDirect を呼び出す前に行う必要があります。そうしないと、SQL_ERROR が返され、"属性値 SQL_SOPT_SS_PARAM_FOCUS が無効です (実行時に 0 である必要があります)" というメッセージを含む、SQLSTATE=HY024 の診断レコードが生成されます。

  4. StrLen_or_IndPtr または SQL_DESC_OCTET_LENGTH_PTR に、SQL_DEFAULT_PARAM (テーブル値パラメータに行が存在しない場合) または次回 SQLExecute または SQLExecDirect を呼び出したときに転送する行数 (テーブル値パラメータに行が存在する場合) を設定します。テーブル値パラメータを構成する列で NULL 値が許容される場合はありますが、テーブル値パラメータ自体では NULL 値が許容されないため、StrLen_or_IndPtr または SQL_DESC_OCTET_LENGTH_PTR に SQL_NULL_DATA を設定することはできません。これに無効な値が設定されている場合、SQLExecute または SQLExecDirect を呼び出すと、SQL_ERROR が返され、"パラメータ <p> の文字列長またはバッファ長が正しくありません" というメッセージを含む、SQLSTATE=HY090 の診断レコードが生成されます。p はパラメータ番号です。

  5. SQLExecute または SQLExecDirect を呼び出します。

列の StrLen_or_IndPtr に SQL_LEN_DATA_AT_EXEC (length) または SQL_DATA_AT_EXEC が設定されている場合は、入力のテーブル値パラメータの列の値を個別に渡すことができます。これは、パラメータの配列を使用するときに値を個別に渡す場合と似ています。実行時データのすべてのパラメータと同様、SQLParamData は、ドライバが要求しているデータが配列のどの行にあるかを示しません。そのため、アプリケーションがこれに対処する必要があります。アプリケーションでは、ドライバが値を要求する順序についてどのような想定も行うことができません。

テーブル値パラメータの可変の行バインド

可変の行バインドの場合、行は実行時にバッチで転送され、アプリケーションは要求時に行をドライバに渡します。これは、各パラメータ値の実行時データに似ています。可変の行バインドでは、アプリケーションによって次の処理が行われます。

  1. 前述の「テーブル値パラメータの固定の行バインド」の手順 1. ~ 3. の説明に従って、パラメータと、テーブル値パラメータの列をバインドします。

  2. 実行時に渡されるすべてのテーブル値パラメータの StrLen_or_IndPtr または SQL_DESC_OCTET_LENGTH_PTR に SQL_DATA_AT_EXEC を設定します。どちらも設定しない場合、前のセクションで説明したように、パラメータが処理されます。

  3. SQLExecute または SQLExecDirect を呼び出します。実行時データ パラメータとして処理される SQL_PARAM_INPUT パラメータまたは SQL_PARAM_INPUT_OUTPUT パラメータが存在する場合は、SQL_NEED_DATA が返されます。この場合、アプリケーションによって次の処理が行われます。

    • SQLParamData を呼び出します。実行時データ パラメータの ParameterValuePtr 値と、リターン コード SQL_NEED_DATA が返されます。すべてのパラメータ データがドライバに渡された場合、SQLParamData によって SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、または SQL_ERROR が返されます。実行時データ パラメータの ParameterValuePtr は、記述子フィールド SQL_DESC_DATA_PTR と同じであり、値を必要とするパラメータを一意に識別するためのトークンと見なすことができます。この "トークン" は、バインド時にアプリケーションからドライバに渡され、実行時にアプリケーションに返されます。
  4. テーブル値パラメータが NULL の場合にテーブル値パラメータの行データを送信するには、テーブル値パラメータに行が存在しない場合は、アプリケーションでは、StrLen_or_Ind に SQL_DEFAULT_PARAM を設定して SQLPutData を呼び出します。

    NULL 以外の TVP については、アプリケーションによって次の処理が行われます。

    • テーブル値パラメータのすべての列の Str_Len_or_Ind に適切な値を設定し、テーブル値パラメータの列のうち、実行時データ パラメータとはならない列のデータ バッファを設定します。通常のパラメータを個別にドライバに渡すことができるように、テーブル値パラメータの列の実行時データを使用することができます。

    • サーバーに送信する行数を Str_Len_or_Ind に設定して SQLPutData を呼び出します。0 から SQL_DESC_ARRAY_SIZE の範囲を超える値と SQL_DEFAULT_PARAM 以外の値はエラーになります。"文字列長またはバッファ長が正しくありません。" というメッセージを含む SQLSTATE HY090 が返されます。0 は、すべての行が送信済みで、テーブル値パラメータのデータが存在しないことを示します (この箇条書きの 2 番目の項目参照)。SQL_DEFAULT_PARAM を使用できるのは、ドライバがテーブル値パラメータのデータを最初に要求するときだけです (この箇条書きの 1 番目の項目参照)。

  5. すべての行が送信されたら、テーブル値パラメータに対して、Str_Len_or_Ind 値を 0 に設定した SQLPutData を呼び出し、手順 3a. に進みます。

  6. 再度 SQLParamData を呼び出します。テーブル値パラメータの列の中に実行時データ パラメータが含まれる場合、実行時データ パラメータは、SQLParamData によって返された値 ValuePtrPtr で識別されます。列の値がすべて使用できる場合、SQLParamData が再びテーブル値パラメータの ParameterValuePtr の値を返し、アプリケーションは再び開始されます。