すべての値がメモリ内にある場合に TVP としてデータを送信する方法 (ODBC)
このトピックでは、すべての値がメモリ内にある場合に、データをテーブル値パラメータとしてストアド プロシージャに送信する方法について説明します。
前提条件
この手順では、次の Transact-SQL がサーバーで実行されていることを前提としています。
create type TVParam as table(ProdCode integer, Qty integer)
create procedure TVPOrderEntry(@CustCode varchar(5), @Items TVPParam,
@OrdNo integer output, @OrdDate datetime output)
as
set @OrdDate = GETDATE();
insert into TVPOrd (OrdDate, CustCode)
values (@OrdDate, @CustCode) output OrdNo);
select @OrdNo = SCOPE_IDENTITY();
insert into TVPItem (OrdNo, ProdCode, Qty)
select @OrdNo, @Items.ProdCode, @Items.Qty
from @Items
データを送信するには
SQL パラメータの変数を宣言します。この場合、テーブル値はすべてメモリ内に保持されているため、テーブル値の列の値は配列として宣言されます。
SQLRETURN r; // Variables for SQL parameters. #define ITEM_ARRAY_SIZE 20 SQLCHAR CustCode[6]; SQLCHAR *TVP = (SQLCHAR *) "TVParam"; SQLINTEGER ProdCode[ITEM_ARRAY_SIZE], Qty[ITEM_ARRAY_SIZE]; SQLINTEGER OrdNo; char OrdDate[23]; // Variables for indicator/length variables associated with parameters. SQLLEN cbCustCode, cbTVP, cbProdCode[ITEM_ARRAY_SIZE], cbQty[ITEM_ARRAY_SIZE], cbOrdNo, cbOrdDate;
パラメータをバインドします。テーブル値パラメータが使用されている場合、パラメータのバインドは 2 段階の処理になります。第 1 段階として、次のように、ストアド プロシージャのパラメータを通常の方法でバインドします。
// Bind parameters for call to TVPOrderEntryDirect. // 1 - Custcode input r = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,SQL_VARCHAR, SQL_C_CHAR, 5, 0, CustCode, sizeof(CustCode), &cbCustCode); // 2 - Items TVP r = SQLBindParameter(hstmt, 2,// ParameterNumber SQL_PARAM_INPUT,// InputOutputType SQL_C_DEFAULT,// ValueType SQL_SS_TABLE,// Parametertype ITEM_ARRAY_SIZE,// ColumnSize: For a table-valued parameter this is the row array size. 0,// DecimalDigits: For a table-valued parameter this is always 0. TVP,// ParameterValuePtr: For a table-valued parameter this is the type name of the //table-valued parameter, and also a token returned by SQLParamData. SQL_NTS,// BufferLength: For a table-valued parameter this is the length of the type name or SQL_NTS. &cbTVP);// StrLen_or_IndPtr: For a table-valued parameter this is the number of rows actually used. // 3 - OrdNo output r = SQLBindParameter(hstmt, 3, SQL_PARAM_OUTPUT,SQL_INTEGER, SQL_C_LONG, 0, 0, &OrdNo, sizeof(SQLINTEGER), &cbOrdNo); // 4 - OrdDate output r = SQLBindParameter(hstmt, 4, SQL_PARAM_OUTPUT,SQL_TYPE_TIMESTAMP, SQL_C_CHAR, 23, 3, &OrdDate, sizeof(OrdDate), &cbOrdDate);
第 2 段階として、テーブル値パラメータの列をバインドします。最初、テーブル値パラメータの序数にフォーカスが設定されます。その後、ストアド プロシージャのパラメータのバインドと同じように、テーブル値の列が SQLBindParameter を使用してバインドされます。ただし、ParameterNumber に列の序数を使用します。テーブル値パラメータがまだある場合は、順番にフォーカスを設定し、その列をバインドします。最後に、パラメータのフォーカスが 0 にリセットされます。
// Bind columns for the table-valued parameter (param 2). // First set focus on param 2. r = SQLSetStmtAttr(hstmt, SQL_SOPT_SS_PARAM_FOCUS, (SQLPOINTER) 2, SQL_IS_INTEGER); // Col 1 - ProdCode r = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,SQL_INTEGER, SQL_C_LONG, 0, 0, ProdCode, sizeof(SQLINTEGER), cbProdCode); // Col 2 - Qty r = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT,SQL_INTEGER, SQL_C_LONG, 0, 0, Qty, sizeof(SQLINTEGER), cbQty); // Reset param focus. r = SQLSetStmtAttr(hstmt, SQL_SOPT_SS_PARAM_FOCUS, (SQLPOINTER) 0, SQL_IS_INTEGER);
パラメータのバッファを設定します。cbTVP は、サーバーに送信される行数に設定されます。
// Populate parameters. cbTVP = 0; // Number of rows available for input. strcpy_s((char *) CustCode, sizeof(CustCode), "CUST1"); cbCustCode = SQL_NTS; ProdCode[cbTVP] = 1215;cbProdCode[cbTVP] = sizeof(SQLINTEGER); Qty[cbTVP] = 5;cbQty[cbTVP] = sizeof(SQLINTEGER); cbTVP++; // Number of rows available for input ProdCode[cbTVP] = 1017;cbProdCode[cbTVP] = sizeof(SQLINTEGER); Qty[cbTVP] = 2;cbQty[cbTVP] = sizeof(SQLINTEGER); cbTVP++; // Number of rows available for input.
プロシージャを呼び出します。
// Call the procedure. r = SQLExecDirect(hstmt, (SQLCHAR *) "{call TVPOrderEntry(?, ?, ?, ?)}",SQL_NTS);