Поделиться через


Как отправить данные в виде параметра, возвращающего табличное значение, со всеми значениями в памяти (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

Отправка данных

  1. Объявление переменных для параметров SQL В данном случае табличное значение полностью содержится в памяти, поэтому значения для столбцов этого табличного значения объявляются как массивы.

    SQLRETURN r;// Variables for SQL parameters.#define ITEM_ARRAY_SIZE 20SQLCHAR 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. Выполните привязку параметров. При использовании имеющих табличное значение параметров процесс привязки параметров состоит из двух этапов. На первом этапе шаговые параметры для хранимой процедуры привязываются обычным путем, как показано ниже.

    // Bind parameters for call to TVPOrderEntryDirect.// 1 - Custcode inputr = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,SQL_VARCHAR, SQL_C_CHAR, 5, 0, CustCode, sizeof(CustCode), &cbCustCode);// 2 - Items TVPr = 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 outputr = SQLBindParameter(hstmt, 3, SQL_PARAM_OUTPUT,SQL_INTEGER, SQL_C_LONG, 0, 0, &OrdNo,   sizeof(SQLINTEGER), &cbOrdNo);// 4 - OrdDate outputr = SQLBindParameter(hstmt, 4, SQL_PARAM_OUTPUT,SQL_TYPE_TIMESTAMP, SQL_C_CHAR, 23, 3, &OrdDate,    sizeof(OrdDate), &cbOrdDate);
    
  3. Второй этап процесса привязки параметров состоит в связывании столбцов для параметра с табличным значением. Сначала фокус параметра устанавливается на порядковом номере параметра с табличным значением. Затем столбцы табличного значения связываются с помощью 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 - ProdCoder = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,SQL_INTEGER, SQL_C_LONG, 0, 0, ProdCode, sizeof(SQLINTEGER), cbProdCode);// Col 2 - Qtyr = 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);
    
  4. Заполните буферы параметра. В качестве значения 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 inputProdCode[cbTVP] = 1017;cbProdCode[cbTVP] = sizeof(SQLINTEGER); Qty[cbTVP] = 2;cbQty[cbTVP] = sizeof(SQLINTEGER); cbTVP++; // Number of rows available for input.
    
  5. Вызовите процедуру:

    // Call the procedure.r = SQLExecDirect(hstmt, (SQLCHAR *) "{call TVPOrderEntry(?, ?, ?, ?)}",SQL_NTS);