Я написал функцию, которая отправляет данные в хранимую процедуру T-SQL с использованием табличных параметров. Ее первый раз, когда я сделал это, и я застрял на этой ошибке:SQL Исходный клиентский интерфейс ошибки 8058 при использовании параметра таблицы, не может диагностировать причину
The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Table-valued parameter 1, to a parameterized string has no table type defined.
К сожалению, я не могу найти какие-либо ресурсы в сети, которые дают решения, как исправить такую ошибку. И из сообщения я остался без понимания, что здесь не так.
Ошибка возникает, когда SQLExecDirectA вызывается в коде ниже.
ErrorCode SQLif::InsertObjectBatch(ObjTypeKey* pObjectTypeKeys, ObjectId* pObjectIds, unsigned int numObjects)
{
ErrorCode ec = ACK;
EnterCriticalSection(m_pcs);
SQLRETURN ret;
SQLHSTMT hStmt;
StorageClass* pStorageClasses = new StorageClass[numObjects];
RevisionId* pRevisionIds = new RevisionId[numObjects];
if (!pStorageClasses || !pRevisionIds)
{
if (pStorageClasses) delete pStorageClasses;
if (pRevisionIds) delete pRevisionIds;
LeaveCriticalSection(m_pcs);
return NACK("SQLif::InsertObjectBack: Allocation failure allocating arrays");
}
for (unsigned int i = 0; i < numObjects; i++)
pStorageClasses[i] = PERSIST;
for (unsigned int i = 0; i < numObjects; i++)
pRevisionIds[i] = 0;
// Variable for TVP row count;
SQLINTEGER cbTVP;
unsigned long long objectIdParam = 0;
SQLLEN objectIdParamLen = sizeof(objectIdParam);
// Allocate a statement handle
if ((ec = AllocStatementHandle(&hStmt)) != ACK)
{
LeaveCriticalSection(m_pcs);
return ec;
}
// Bind paramters for call
if (ec == ACK)
{
ret = SQLBindParameter(hStmt, // Statement handle
1, // ParameterNumber
SQL_PARAM_INPUT, // InputOutputType
SQL_C_DEFAULT, // ValueType
SQL_SS_TABLE, // ParameterType
(SQLINTEGER) numObjects, // Number of rows in TVP
0, // Number of columns in TVP
NULL, // not needed
NULL, // not needed
&cbTVP);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::InsertObjectBatch: Binding to parameter 1 failed");
}
// Bind colums for the TVP (param 1)
if (ec == ACK)
{
ret = SQLSetStmtAttr(hStmt, SQL_SOPT_SS_PARAM_FOCUS, (SQLPOINTER) 1, SQL_IS_INTEGER);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::InsertObjectBatch: Setting Focus to TVP failed");
}
// Bind column 1
if (ec == ACK)
{
ret = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, pStorageClasses, sizeof(SQLINTEGER), NULL);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::InsertObjectBach: Binding to column 1 of TVP failed");
}
// Bind column 2
if (ec == ACK)
{
ret = SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, pObjectTypeKeys, sizeof(SQLUINTEGER), NULL);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::InsertObjectBach: Binding to column 2 of TVP failed");
}
// Bind column 3
if (ec == ACK)
{
ret = SQLBindParameter(hStmt, 3, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT, 0, 0, pRevisionIds, sizeof(SQLUBIGINT), NULL);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::InsertObjectBach: Binding to column 3 of TVP failed");
}
// Release focus
if (ec == ACK)
{
ret = SQLSetStmtAttr(hStmt, SQL_SOPT_SS_PARAM_FOCUS, (SQLPOINTER) 0, SQL_IS_INTEGER);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::InsertObjectBatch: Resetting Focus failed");
}
// Initialize row count
cbTVP = numObjects;
if (ec == ACK)
{
ret =SQLExecDirectA(hStmt, (SQLCHAR*)"EXEC Proc_InsertObjectBatch ?", SQL_NTS);
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = GetErrorMessage(hStmt);
}
if (ec == ACK)
{
ret = SQLBindCol(hStmt, 1, SQL_C_UBIGINT, &objectIdParam, sizeof(objectIdParam), &objectIdParamLen);
if (ret != SQL_SUCCESS) ec = NACK("SQLif::InsertObjectBatch: Binding to column 1 failed");
}
bool bHasData = false;
unsigned int i = 0;
if (ec == ACK)
{
while ((ret = SQLFetch(hStmt)) != SQL_NO_DATA)
{
if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) ec = NACK("SQLif::RetrieveAttribute: Unable to fetch rows");
bHasData = true;
pObjectIds[i] = objectIdParam;
}
}
FreeStatementHandle(hStmt);
LeaveCriticalSection(m_pcs);
return ACK;
}
Это соответствующая хранимая процедура.
Это тип таблицы.
-- Create ObjectTableType
CREATE TYPE ObjectTableType AS TABLE
(
stkey integer,
otkey integer,
orev bigint
)
Любая помощь, как исправить это было бы весьма полезно.