2015-11-02 64 views
2

你好在那里研究C和ODBC 我在调用SQLExecDirect函数时出错。 请帮我 这里是代码SQLExecDirect结果-1状态24000在C

#include <Windows.h> 
#include <sql.h> 
#include <sqlext.h> 

int main(void) 
{ 
    //DB connect example 
    SQLRETURN nResult  = 0; 
    SQLHANDLE handleEnv = 0; 
    nResult = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, (SQLHANDLE*)&handleEnv); 
    //nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC2, SQL_IS_INTEGER); 
    nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER); 
    nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)SQL_CP_ONE_PER_HENV, SQL_IS_INTEGER); 

    SQLHANDLE handleDBC = 0; 
    nResult = SQLAllocHandle(SQL_HANDLE_DBC, handleEnv, (SQLHANDLE*)&handleDBC); 

    SQLCHAR  strConnect[ 256 ]  = "DSN=MY TEST DB; UID=TESTsa; PWD=TESTpw"; 
    SQLCHAR  strConnectOut[ 1024 ] = {0}; 
    SQLSMALLINT nNumOut     = 0; 
    nResult = SQLDriverConnect(handleDBC, NULL, (SQLCHAR*)strConnect, SQL_NTS, (SQLCHAR*)strConnectOut, sizeof(strConnectOut), 
           &nNumOut, SQL_DRIVER_NOPROMPT); 

    SQLHSTMT handleStatement = 0; 
    //nResult = ::SQLAllocStmt(handleDBC, &handleStatement); 
    nResult = SQLAllocHandle(SQL_HANDLE_STMT, handleDBC, (SQLHANDLE*)&handleStatement); 

    SQLHSTMT hstmt  = handleStatement; 
    int   sqlResultOutput = 0; 

    SQLINTEGER cbValue  = 0; 
    nResult = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &sqlResultOutput, 0, &cbValue); 

    //here is the problem 
    nResult = SQLExecDirect(hstmt, (SQLTCHAR*) "{CALL my_TEST_SP(?)}", SQL_NTS); 
    //nResult Value is -1 and SQL State is 24000 

    return 0; 
} 

每次调用的结果是好的。返回SQL_SUCCESS但都一个 SQLExecDirect函数是返回-1和SQLSTATE 24000

存储过程是简单的像这样

CREATE PROCEDURE my_TEST_SP 
@retValue int = 0 output 
AS 
BEGIN 
    SET NOCOUNT ON 

    SET @retValue = 0 

    SELECT myTestCol 
    FROM tTestTable 

    IF @@ERROR <> 0 
    BEGIN 
    SET @retValue = -1 
    END 
END 

我的操作系统是Windows7的。 使用visual studio 2010 sp1,sqlserver 2012

我想念什么?请告诉我,并有一个美好的一天:)

+0

可能的重复http://stackoverflow.com/questions/3727907/sqlstate-24000-invalid-cursor-state –

+0

对不起,我检查,但我不明白它。但感谢您的评论 –

+0

令人困惑的是,我可以使用'SQL Server的ODBC驱动程序11'和Windows 7上的Visual Studio 2013运行这个稍微修改过的代码(连接字符串,使用SQLWCHAR)就可以很好地对付SQL Server 2014. – erg

回答

0

主要区别似乎是odbc驱动程序版本。我的版本是2014.120.2000.08。我不认为这是由于不同的视觉工作室版本 - 我认为他们都在引擎盖下使用相同的odbc32.lib

下面的代码工作对我来说:我改变了存储过程返回的东西,是不为0(验证我其实可以读取返回的数据):

@retValue int = 0 output 
AS 
BEGIN 
    SET NOCOUNT ON 

    SET @retValue = 3499 

    SELECT myTestCol 
    FROM tTestTable 

    IF @@ERROR <> 0 
    BEGIN 
    SET @retValue = -1 
    END 
END 

我用下面的代码在Visual工作室2013:

void printErrDbc(SQLHDBC hDbc) 
{ 
    SQLSMALLINT recNr = 1; 
    SQLRETURN ret = SQL_SUCCESS; 
    while (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
    { 
     SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1]; 
     SQLWCHAR sqlState[5 + 1]; 
     errMsg[0] = 0; 
     SQLINTEGER nativeError; 
     SQLSMALLINT cb = 0; 
     ret = SQLGetDiagRec(SQL_HANDLE_DBC, hDbc, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb); 
     if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
     { 
      std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl; 
     } 
     ++recNr; 
    } 
} 

void printErrStmt(SQLHSTMT hStmt) 
{ 
    SQLSMALLINT recNr = 1; 
    SQLRETURN ret = SQL_SUCCESS; 
    while (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
    { 
     SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1]; 
     SQLWCHAR sqlState[5 + 1]; 
     errMsg[0] = 0; 
     SQLINTEGER nativeError; 
     SQLSMALLINT cb = 0; 
     ret = SQLGetDiagRec(SQL_HANDLE_STMT, hStmt, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb); 
     if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
     { 
      std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl; 
     } 
     ++recNr; 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    //DB connect example 
    SQLRETURN nResult = 0; 
    SQLHANDLE handleEnv = 0; 
    nResult = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, (SQLHANDLE*)&handleEnv); 
    //nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC2, SQL_IS_INTEGER); 
    nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER); 
    nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)SQL_CP_ONE_PER_HENV, SQL_IS_INTEGER); 

    SQLHANDLE handleDBC = 0; 
    nResult = SQLAllocHandle(SQL_HANDLE_DBC, handleEnv, (SQLHANDLE*)&handleDBC); 

    SQLWCHAR  strConnect[256] = L"DSN=test;UID=sa;PWD=MySecretPassword"; 
    SQLWCHAR  strConnectOut[1024] = { 0 }; 
    SQLSMALLINT nNumOut = 0; 
    nResult = SQLDriverConnect(handleDBC, NULL, (SQLWCHAR*)strConnect, SQL_NTS, (SQLWCHAR*)strConnectOut, sizeof(strConnectOut), 
     &nNumOut, SQL_DRIVER_NOPROMPT); 
    if (!SQL_SUCCEEDED(nResult)) 
    { 
     printErrDbc(handleDBC); 
    } 

    SQLHSTMT handleStatement = 0; 
    //nResult = ::SQLAllocStmt(handleDBC, &handleStatement); 
    nResult = SQLAllocHandle(SQL_HANDLE_STMT, handleDBC, (SQLHANDLE*)&handleStatement); 

    SQLHSTMT hstmt = handleStatement; 
    int   sqlResultOutput = 0; 

    SQLINTEGER cbValue = 0; 
    nResult = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &sqlResultOutput, 0, &cbValue); 

    //here is the problem 
    nResult = SQLExecDirect(hstmt, (SQLWCHAR*)L"{CALL my_TEST_SP(?)}", SQL_NTS); 
    if (!SQL_SUCCEEDED(nResult)) 
    { 
     printErrStmt(hstmt); 
    } 
    nResult = SQLMoreResults(hstmt); 
    if (!(SQL_SUCCEEDED(nResult) || nResult == SQL_NO_DATA)) 
    { 
     printErrStmt(hstmt); 
    } 
    std::wcout << L"Value of sqlResultOutput is: " << sqlResultOutput << std::endl; 

    return 0; 
} 

在ODBC数据源管理器,我创建使用ODBC Driver 11 for SQL Server与版本2014.120.2000.08名为test相应的DSN。在结束时,DSN条目显示以下属性(在对话框中,你可以打Test Data Source...):

Microsoft ODBC Driver for SQL Server Version 12.00.2000 

Data Source Name: test 
Data Source Description: 
Server: .\SQLSERVERINSTANCE 
Use Integrated Security: Yes 
Database: Test 
Language: (Default) 
Data Encryption: No 
Trust Server Certificate: No 
Multiple Active Result Sets(MARS): No 
Mirror Server: 
Translate Character Data: Yes 
Log Long Running Queries: No 
Log Driver Statistics: No 
Use Regional Settings: No 
Use ANSI Quoted Identifiers: Yes 
Use ANSI Null, Paddings and Warnings: Yes 

如果我运行此示例应用程序,我得到预期输出:

Value of sqlResultOutput is: 3499 

,所以我会建议您尝试使用SQL Server的最新ODBC驱动程序。我认为这是下载这里:http://www.microsoft.com/de-ch/download/details.aspx?id=36434

+0

谢谢你的答案我只是下载msodbcsql.msi并通过链接安装它,但ODBC驱动程序版本并没有改变奇怪它仍然开始2011不2014甚至我卸载ODBC驱动程序和重用msodbcsql.msi文件虐待保持尝试安装odbc驱动程序版本2014 –

+0

我无法找到2014版本的odbc驱动程序。只有我可以找到2011年不知道为什么。可能是我需要VS2013或SQLserver2014这么伤心。但感谢您的回答erg –

+0

是的,您可以尝试使用Sql Server 2014.我一直在使用SQL Server 2014 Express Edition进行测试(可以从Microsoft免费下载)。希望这有帮助,祝你好运。 – erg