2017-10-17 105 views
0

我有以下代码(使用ODBC连接到一个SQL数据库): 连接正常,也是第一个SQL_ExecuteQuery(),但第二个和第三个SQL_ExecuteQuery()将返回一个错误(SQLExecDirect的返回码-1 )。 我假设,“语句句柄hstmt”将在第一次执行后被覆盖。但我怎么能避免这种情况?非常感谢。如何设置ODBC连接以在C++中执行多个查询(SQLExecDirect)?

SQLHENV henv = SQL_NULL_HENV; 
SQLHDBC hdbc = SQL_NULL_HDBC; 
SQLHDBC hstmt= SQL_NULL_HSTMT; 
SQLRETURN retcode = SQL_SUCCESS; 

//Connect function 
int SQL_Connect() 
{ 
SQLWCHAR OutConnStr[255]; 
SQLSMALLINT OutConnStrLen; 

// Allocate environment handle 
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); 

// Set the ODBC version environment attribute 
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 
{ 
    retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0); 

    // Allocate connection handle 
    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 
    { 
     retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); 

     // Set login timeout to 5 seconds 
     if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 
     { 
      SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0); 

      retcode = SQLDriverConnect(hdbc, 
             NULL, 
             #ifdef IPC 
              (SQLWCHAR *)L"DSN=TEST;Description=ODK;UID=FFF;PWD=XXX;Trusted_Connection=No;DATABASE=DDD;", 
             #else 
              (SQLWCHAR *)L"DSN=ODKSQL64;Description=ODK;UID=auto;PWD=Visu_KDbos;Trusted_Connection=No;DATABASE=Giesserei_BKO;", 
             #endif 
             SQL_NTS, 
             OutConnStr, 
             255, 
             &OutConnStrLen, 
             SQL_DRIVER_NOPROMPT); 

      // Allocate statement handle 
      if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 
      { 
       retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); 

       cout<<"Verbindung OK"<<std::endl; 
      } 
     } 
    } 
} 
return retcode; 
} 

//Disonnect function 
int SQL_Disconnect() 
{ 
SQLFreeHandle(SQL_HANDLE_STMT, hstmt); 
SQLDisconnect(hdbc); 
SQLFreeHandle(SQL_HANDLE_DBC, hdbc); 
SQLFreeHandle(SQL_HANDLE_ENV, henv); 

return 1; 
} 

//Query function 
int SQL_ExecuteQuery() 
{ 
short rc; 
char material[50]; 
SQLINTEGER strlenmaterial; 

//prepare query 
std::wstring SQL_Statement = L"SELECT blablabla"; 

rc = SQLExecDirect(hstmt, const_cast<SQLWCHAR*>(SQL_Statement.c_str()), SQL_NTS); 

if (rc==SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO) { 
     SQLBindCol(hstmt, 1, SQL_C_CHAR, &material, (SQLINTEGER) sizeof(material), &strlenmaterial); 
     while (1) { 
      rc = SQLFetch(hstmt); 
      if (rc==SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO) { 
       rc = 1; 
      }else { 
       break; 
      } 
     } 
    } else { 
     //no data found 
     rc = 3; 
    } 

return rc; 
} 


int main() 
{ 
short rc; 

rc = SQL_Connect(); 

rc = SQL_ExecuteQuery(); 
rc = SQL_ExecuteQuery(); 
rc = SQL_ExecuteQuery(); 

rc = SQL_Disconnect(); 


return 0; 
} 

回答

0

您可以重新使用HSTMT句柄,但在运行新查询之前,需要关闭待定游标。当您使用SQLBindCol绑定列时,还需要解除列绑定,然后再次绑定它们。

在你SQL_ExecuteQuery(),从函数调用返回之前:

SQLFreeStmt(hstmt, SQL_UNBIND) 
SQLFreeStmt(hstmt, SQL_CLOSE) 

现在你已经准备好执行另一个查询,再结合并获取结果。

请注意,您也可以更改程序的逻辑并绑定一次,然后跳过解除绑定步骤:如果您知道对同一列的结果始终感兴趣,则可以将列在执行查询之前。然后,您可以执行查询,读取结果,使用SQL_CLOSE选项呼叫SQLFreeStmt,然后重新执行查询。

在这里看到更多的细节: https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlfreestmt-function

+0

非常感谢您的回答。现在一切正常。 – Osti

+0

@Osti:欢迎。你能接受它作为答案吗,要说清楚它解决了你的问题? – erg

相关问题