ODBC-编码在C 中准备的语句

ODBC - Coding Prepared Statements in C++

本文关键字:语句 编码 ODBC-      更新时间:2023-10-16

嗨,

插入学习如何开发ODBC SQL驱动程序和数据源的东西,但我似乎已经遇到了一些障碍。我目前正在使用A数据库上的已准备好的语句,其中包含以下语句:

select * from TEST1 where NAME = ? and LOCATION__LATITUDE__S = ?

在英语中,查找带有指定名称和纬度坐标的所有记录。我可以使用ODBCTEST应用程序进行以上操作,因此我知道我可以连接到数据源并使用参数化查询查询。这是我有问题功能的代码:

void ExecPreparedStatement(const char* stmt) {
    HSTMT hstmt;
    SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    RETCODE rc = SQLPrepare(hstmt, (WCHAR*)stmt, SQL_NTS);
    SQLSMALLINT numParams;
    rc = SQLNumParams(hstmt, &numParams);
    WCHAR* param1 = (WCHAR*)L"Jacob";
    SQLFLOAT param2 = 40.0;
    rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 80, 0, (SQLPOINTER)param1, 300, NULL);
    rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, &param2, 300, NULL);
    rc = SQLExecute(hstmt); /* <fails here> */
    SQLSMALLINT numCols;
    SQLNumResultCols(hstmt, &numCols);
    DisplayRecords(hstmt, numCols);
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}

这个应该给我从测试应用程序中给我相同的结果:3个属性的记录(3行,13列)。相反,它在执行时失败。为了易于阅读,我已经从代码中删除了所有retcode处理,但是我确实在那里删除了它来检查语句是否已完成并在失败时优雅地处理。我在这里必须有一些误解 - 它还向我表明,语句的参数数为0(带有numparams varible);我认为这是因为它应该在执行呼叫后放置,但是我现在无法测试,因为我从未达到执行点。

有什么想法吗?把我的头撞在这里的砖墙上;事实证明,MSDN和其他在线资源对此有所帮助。

澄清主要问题:有人知道为什么执行功能失败吗?

找到答案

这个问题是通过滥用的铸造畸形的。我不是将const char*字符串传递给该函数,而是将其传递给WCHAR*casted String,然后在函数中使用WCHAR*。现在看起来像这样的功能代码:

HSTMT hstmt;
SQLAllocStmt(hdbc, &hstmt);
TryODBC(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, stmt, SQL_NTS));
// Prepare passes test - we return 0.
WCHAR* param1 = (WCHAR*)L"Jacob";
TryODBC(hstmt, SQL_HANDLE_STMT, 
    SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, 
        SQL_WVARCHAR, 80, 0, (SQLPOINTER)param1, 300, NULL)
);
TryODBC(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt));
SQLSMALLINT numCols;
TryODBC(hstmt, SQL_HANDLE_STMT, SQLNumResultCols(hstmt, &numCols));
DisplayRecords(hstmt, numCols);
SQLFreeStmt(hstmt, SQL_CLOSE);

其中tryodbc()是一个函数如下:

bool disconnectOnError = false;
if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_ERROR) {
    if (!Success(rc)) {
        disconnectOnError = true;
    }
    SQLWCHAR       state[6], errorMsg[SQL_MAX_MESSAGE_LENGTH];
    SQLINTEGER    nativeError;
    SQLSMALLINT   i = 1, msgLen;
    while ((rc = SQLGetDiagRec(handleType, handle, i, state, 
        &nativeError, errorMsg, sizeof(errorMsg), &msgLen)) != SQL_NO_DATA)
    {
        ShowMessage(nativeError, errorMsg);
        i++;
    }
}
if (disconnectOnError) {
    Disconnect(-1);
}

非常感谢@erg将我引向sqlgetDiagrec()函数。

您正在传递一个宽字符串,但指定sql_c_char作为参数类型,这应该是sql_c_wchar.

300,因为您的BufferLength参数没有任何意义,因为字符串参数通过了正确的字节数,对于Param2,只需通过0(对于非字符或二进制串联数据而忽略了BufferLength)。

,您确实需要在每个ODBC调用后检查错误代码,如果是错误,则将诊断丢弃。要么打开跟踪连接属性并查看结果。

在原始问题中指出的答案。