テーブル値パラメーターおよび列の値のバインドとデータ転送
適用対象: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW)
テーブル値パラメーター (TVP) は、他のパラメーターと同様に、サーバーに渡される前にバインドする必要があります。 アプリケーションは、SQLBindParameter を使用するか、SQLSetDescField または SQLSetDescRec を呼び出す同等の呼び出しを使用して、他のパラメーターをバインドするのと同じ方法で、テーブル値パラメーターをバインドします。 テーブル値パラメーター用のサーバーのデータ型は SQL_SS_TABLE です。 C 型は SQL_C_DEFAULT または SQL_C_BINARY として指定できます。
SQL Server 2008 (10.0.x) 以降では、入力テーブル値パラメーターのみがサポートされています。 したがって、SQL_DESC_PARAMETER_TYPEを SQL_PARAM_INPUT 以外の値に設定しようとすると、SQLSTATE = HY105 とメッセージ "Invalid parameter type" の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を返します。 診断レコードは SQLSTATE=07S01 で生成され、"パラメーター <p> の既定のパラメーターが無効です" というメッセージが表示されます。ここで、 <p> はクエリ ステートメントの TVP の序数です。
Note
SQL_DEFAULT_PARAMは行を示さないため、テーブル値パラメーターには設定できる既定値がありません。 したがって、行がない場合は、バインドする列はありません。
テーブル値パラメーターをバインドしたら、アプリケーションでは、次に、テーブル値パラメーターの各列をバインドする必要があります。 これを行うために、アプリケーションは最初に SQLSetStmtAttr を呼び出して、テーブル値パラメーターの序数にSQL_SOPT_SS_PARAM_FOCUSを設定します。 アプリケーションは、SQLBindParameter、SQLSetDescRec、および SQLSetDescField の各ルーチンの呼び出しによって、テーブル値パラメーターの列をバインドします。 SQL_SOPT_SS_PARAM_FOCUSを 0 に設定すると、通常の最上位パラメーターで動作する SQLBindParameter、SQLSetDescRec、および SQLSetDescField の通常の効果が復元されます。
Note
unixODBC 2.3.1 から 2.3.4 の Linux および Mac ODBC ドライバーの場合、SQL_CA_SS_TYPE_NAME記述子フィールドを使用して SQLSetDescField を使用して TVP 名を設定する場合、unixODBC は、(SQLSetDescFieldA / SQLSetDescFieldW) という正確な関数に応じて ANSI 文字列と Unicode 文字列の間で自動的に変換されません。 TVP 名を設定するには、常に SQLBindParameter または SQLSetDescFieldW と Unicode (UTF-16) 文字列を使用する必要があります。
テーブル値パラメーター自体の実際のデータは送受信されませんが、テーブル値パラメーターを構成する各列のデータは送受信されます。 テーブル値パラメーターは擬似列であるため、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か、名前の文字列長にサイズ (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 つのデータ転送モードがサポートされています。
テーブル値パラメーターの固定の行バインド
固定の行バインドの場合、アプリケーションでは、使用可能なすべての入力列の値に対して十分な大きさのバッファー (バッファー配列) を割り当てます。 このアプリケーションによって次の処理が行われます。
SQLBindParameter、SQLSetDescRec、または SQLSetDescField 呼び出しを使用して、すべてのパラメーターをバインドします。
- SQL_DESC_ARRAY_SIZE に各テーブル値パラメーターの転送可能な最大行数を設定します。 これは、SQLBindParameter 呼び出しで実行できます。
SQLSetStmtAttr を呼び出して、各テーブル値パラメーターの序数にSQL_SOPT_SS_PARAM_FOCUSを設定します。
テーブル値パラメーターごとに、SQLBindParameter、SQLSetDescRec、または SQLSetDescField 呼び出しを使用して、テーブル値パラメーター列をバインドします。
既定値を持つテーブル値パラメーター列ごとに、SQLSetDescField を呼び出してSQL_CA_SS_COL_HAS_DEFAULT_VALUEを 1 に設定します。
SQLSetStmtAttr を呼び出して、SQL_SOPT_SS_PARAM_FOCUSを 0 に設定します。 これは、SQLExecute または SQLExecDirect が呼び出される前に行う必要があります。 それ以外の場合は、SQL_ERRORが返され、SQLSTATE=HY024 とメッセージ "Invalid attribute value, SQL_SOPT_SS_PARAM_FOCUS (must be zero at execution time). (実行時にゼロにする必要があります)" というメッセージを含む診断レコードが生成されます。
テーブル値パラメーターに行がない場合は StrLen_or_IndPtr またはSQL_DESC_OCTET_LENGTH_PTRをSQL_DEFAULT_PARAMに設定します。テーブル値パラメーターに行がある場合は、SQLExecute または SQLExecDirect の次の呼び出しで転送される行数を設定します。 StrLen_or_IndPtr またはSQL_DESC_OCTET_LENGTH_PTRをテーブル値パラメーターのSQL_NULL_DATAに設定することはできません。テーブル値パラメーターは null 許容ではありません (ただし、テーブル値パラメーターの構成列は null 許容である可能性があります)。 これが無効な値に設定されている場合、SQLExecute または SQLExecDirect はSQL_ERRORを返し、SQLSTATE=HY090 とメッセージ "Invalid string or buffer length for parameter <p>" (p はパラメーター番号) で診断レコードが生成されます。
SQLExecute または SQLExecDirect を呼び出します。
入力テーブル値パラメーターの列値は、 StrLen_or_IndPtr が列のSQL_LEN_DATA_AT_EXEC (length) またはSQL_DATA_AT_EXECに設定されている場合に、一部で渡すことができます。 これは、パラメーターの配列を使用するときに値を個別に渡す場合と似ています。 すべての実行時データ パラメーターと同様に、SQLParamData では、ドライバーがデータを要求している配列の行は示されません。アプリケーションがこれを行う必要があります。 アプリケーションは、ドライバーが値を要求する順序に関する仮定を行うことはできません。
テーブル値パラメーターの可変の行バインド
可変行バインドの場合、行は実行時にバッチで転送され、アプリケーションは必要に応じてドライバーに行を渡します。 これは、各パラメーター値の実行時データに似ています。 可変の行バインドでは、アプリケーションによって次の処理が行われます。
前のセクション「固定テーブル値パラメーター行バインド」の手順 1 から 3 で説明したように、パラメーターとテーブル値パラメーター列をバインドします。
実行時にSQL_DATA_AT_EXECに渡されるテーブル値パラメーターの StrLen_or_IndPtr またはSQL_DESC_OCTET_LENGTH_PTRを設定します。 どちらも設定されていない場合、パラメーターは前のセクションで説明したように処理されます。
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を返します。 実行時データ パラメーターの場合、記述子フィールドSQL_DESC_DATA_PTRと同じ ParameterValuePtr は、値が一意に必要なパラメーターを識別するためのトークンと見なすことができます。 この "トークン" は、バインド時にアプリケーションからドライバーに渡され、実行時にアプリケーションに返されます。
null テーブル値パラメーターのテーブル値パラメーター行データを送信するために、テーブル値パラメーターに行がない場合、アプリケーションは sqlPutData を呼び出し、 StrLen_or_Ind を SQL_DEFAULT_PARAM に設定します。
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 番目の項目参照)。
すべての行が送信されたら、 Str_Len_or_Ind 値が 0 のテーブル値パラメーターに対して SQLPutData を呼び出し、上記の手順 3a に進みます。
SQLParamData をもう一度呼び出します。 テーブル値パラメーター列の中に実行時のデータ パラメーターがある場合、これらは SQLParamData によって返される値 ValuePtrPtr によって識別されます。 すべての列値が使用可能な場合、SQLParamData はテーブル値パラメーターの ParameterValuePtr 値を返し、アプリケーションが再度開始されます。