如何在 c++ 中设置 ODBC 连接以执行多个查询 (SQLExecDirect)

How do I setup an ODBC connection to perform multiple querys(SQLExecDirect) in c++?

本文关键字:执行 查询 SQLExecDirect 连接 c++ ODBC 设置      更新时间:2023-10-16

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

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;
}

可以重复使用 HSTMT 句柄,但在运行新查询之前,需要关闭挂起的游标。使用 SQLBindCol 绑定列时,还需要在再次绑定列之前取消绑定列。

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

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

现在,您已准备好执行另一个查询,再次绑定并获取结果。

请注意,您还可以更改程序的逻辑,并且只绑定一次,然后跳过取消绑定步骤:如果您知道您总是对同一列的结果感兴趣,则可以在执行查询之前绑定该列。然后,您可以执行查询、读取结果、使用 SQL_CLOSE 选项调用 SQLFreeStmt,然后重新开始执行查询。

有关更多详细信息,请参阅此处:https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlfreestmt-function