2017-10-17 90 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