SQLFetch () error with SQLState 24000 (Invalid cursor)
First of all, this question is not a duplicate:
- SQLSTATE 24000 - Invalid Cursor State
- Invalid cursor state, SQL state 24000 in SQLExecDirect
- One of the SELECTs with error uses unixOdbc - SQLSTATE [24000]: Invalid cursor state
how it goes with a pure unified SQL environment that hasn't done anything before!
I am trying to execute a stored procedure with a prepared SQL statement with the following C ++ ODBC code:
void ItemDBManager::UpgradeItem(SQLHSTMT hstmt, QUERY_UPGRADE_ITEM_PARAMS* upgradeItemParams)
{
// Preparing of the Query
RETCODE ret = SQLPrepare(hstmt, (UCHAR*)"{call dbo.upgrade_Item(?,?)}", SQL_NTS);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
// Get diagnostics for the error and log it to a file
ProcessSQLError(SQL_HANDLE_STMT, hstmt, "dbo.upgrade_Item failed!");
SQLFreeStmt(hstmt, SQL_CLOSE);
return;
}
// Binding of Parameters
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &upgradeItemParams->OldItemUniqueNumber, 0, NULL);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &upgradeItemParams->UpgradedItemUID, 0, NULL);
// Binding of the Result
SQLINTEGER cb[44];
fill_n(cb, 44, SQL_NTS);
ITEM newItem; // My struct to hold the data returned by the Stored Procedure
// Binding of result Columns
int coldIdx = 0;
SQLBindCol(hstmt, ++colIdx, SQL_C_SBIGINT, &storeItem.UniqueNumber, 0, &cb[colIdx]);
SQLBindCol(hstmt, ++colIdx, SQL_C_ULONG, &storeItem.AccountUniqueNumber, 0, &cb[colIdx]);
[...]
// Zeroing the resulting struct
memset(&newItem, 0x00, sizeof(ITEM));
// Execution of the Statement
ret = SQLExecute(hstmt);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
// Get diagnostics for the error and log it to a file
ProcessSQLError(SQL_HANDLE_STMT, hstmt, "dbo.upgrade_Item failed!");
SQLFreeStmt(hstmt, SQL_CLOSE);
return;
}
// Fetching of a single result row
ret = SQLFetch(hstmt);
if (ret == SQL_NO_DATA || (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO))
{
// <-- The Debugger enters here with the return code of -1 !!!!
// Get diagnostics for the error and log it to a file
ProcessSQLError(SQL_HANDLE_STMT, hstmt, "dbo.upgrade_Item failed!");
SQLFreeStmt(hstmt, SQL_CLOSE);
return;
}
[...] // Further Handling of the resulted ITEM Struct and freeing of the SQL Statement
}
The debugger enters the last IF-Statement with ReturnCode -1
, which is generic SQL_ERROR.
After receiving the Rect error diagnostics, I get the following output:
06-24 14:05:19| szSqlState = 24000 06-24 14:05:19| pfNativeError = 0 06-24 14:05:19| szErrorMsg = [Microsoft][ODBC SQL Server Driver]Invalid Cursorstatus 06-24 14:05:19| pcbErrorMsg = 58 06-24 14:05:19| ODBCRowNumber = -1 06-24 14:05:19| SSrvrLine = -1 06-24 14:05:19| SSrvrMsgState = 0 06-24 14:05:19| SSrvrSeverity = 0 06-24 14:05:19| SSrvrProcname = 06-24 14:05:19| SSrvrSrvname =
Executing the query directly in Microsoft SQL Management Studio gives me great results, not errors.
What is the reason for this error? How can I debug it further?
Also, the contents of the stored procedure are dbo.upgrade_Item
:
-- Stored Procedure dbo.upgrade_Item
@i_OldStoreUID BIGINT,
@i_NewItemNum INT
AS
DECLARE @insertedIDs TABLE(Id BIGINT)
-- Updating of the ItemStore Table
INSERT INTO td_ItemStore (*my columns*)
OUTPUT INSERTED.UniqueNumber INTO @insertedIDs
SELECT *my columns*, @i_NewItemNum
FROM td_ItemStore
WHERE UniqueNumber = @i_OldStoreUID
-- Returning the new inserted Item
SELECT * FROM td_ItemStore WHERE UniqueNumber = (SELECT TOP 1 Id FROM @insertedStoreUIDs)
Any help is greatly appreciated!
Apparently I had the same problem as in this question: PDO with MSSQL returns an invalid cursor
The problem was with my stored procedure. To get the correct cursor I had to disable the output of the processed lines by settingNOCOUNT ON
Fixed procedure:
-- Stored Procedure dbo.upgrade_Item
@i_OldStoreUID BIGINT,
@i_NewItemNum INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @insertedIDs TABLE(Id BIGINT)
-- Updating of the ItemStore Table
INSERT INTO td_ItemStore (*my columns*)
OUTPUT INSERTED.UniqueNumber INTO @insertedIDs
SELECT *my columns*, @i_NewItemNum
FROM td_ItemStore
WHERE UniqueNumber = @i_OldStoreUID
-- Returning the new inserted Item
SELECT * FROM td_ItemStore WHERE UniqueNumber = (SELECT TOP 1 Id FROM @insertedStoreUIDs)
END