【发布时间】:2018-09-25 21:11:09
【问题描述】:
我正在使用 Microsoft 的 ODBC 驱动程序将 C++/Linux 应用程序连接到远程运行的 SQL Server 数据库,当我尝试连接到数据库时,调用失败并显示 SQL_INVALID_HANDLE。阅读他们的documentation,我发现:
SQL_INVALID_HANDLE 由于环境、连接、语句或描述符句柄无效,函数失败。这表示编程错误。 SQLGetDiagRec 或 SQLGetDiagField 没有其他信息可用。仅当句柄为空指针或类型错误时才返回此代码,例如为需要连接句柄的参数传递语句句柄时。
很公平,但是在连接语句之前创建句柄和环境时,我没有任何错误。此外,对于第二个参数,他们的文档说如果没有桌面窗口(就像这个 linux 控制台应用程序一样),我可以传入一个空指针。这是一个MVCE,改编自微软的example program:
#include "sql.h"
#include "sqlext.h"
#include "msodbcsql.h"
#include <iostream>
#include <string>
int main(int, char**)
{
using std::cerr;
using std::endl;
SQLHENV henv;
SQLHDBC hdbc;
HWND dhandle = nullptr; // no desktop handle in linux
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLAllocHandle (environment) failed " << retcode << endl;
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLSetEnvAttr failed " << retcode << endl;
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLAllocHandle (connection) failed " << retcode << endl;
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLSetConnectAttr failed " << retcode << endl;
std::string dsn = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=*.*.*,1433;DATABASE=***;UID=***;PWD=***";
retcode = SQLDriverConnect(hdbc, dhandle, (SQLCHAR*)dsn.c_str(), dsn.length(), OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_PROMPT);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLDriverConnect failed " << retcode << endl;
// cleanup code redacted for brevity
return 0;
}
程序输出SQLDriverConnect failed -2,即SQL_INVALID_HANDLE。我难住了。 hdbc 显然是正确的类型,在调试器中检查它显示它不为空。
值得注意的是,完全相同的连接字符串在使用pyodbc 的python 程序中工作。不过,似乎 C++ 程序甚至没有看到那个字符串。它只是不喜欢我发送到连接调用的句柄。
Microsoft 的文档清楚地表明它们不提供其他信息。如果有人可以提供有关如何诊断/调试此问题的任何指导,我将不胜感激。
此应用在 Centos 7 上使用 gcc 4.9.1。
【问题讨论】:
-
我会在没有这些属性函数的情况下尝试它——它们看起来不正确,而且可能没有必要。
-
@NeilButterworth 删除它们的结果相同。
-
if ((!retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))- 括号错误。 -
好收获。但我修复了它并没有改变结果。
-
请用更正的代码编辑您的问题
标签: c++ sql-server odbc