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

时间:2017-10-17 12:36:52

标签: c++ sql odbc

我有以下代码(使用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;
}

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

请点击此处了解更多详情: https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlfreestmt-function