我在项目中使用ODBC API 进行数据库操作,实际开发中遇到一个非常郁闷的问题:无法取得连接超时和设置查询超时!为了进行验证,我特意写了一个测试程序。(后面的帖子中我会贴出代码)
下面时测试程序执行的结果:连接Mysql数据库的执行的结果是:
ODBC Version is: 3               //查询ODBC 版本的结果
Login Timeout is: 3              //查询登录超时的结果
Error Get Connection timeout -1  //设置连接超时为3秒时,出错信息
Error [Microsoft][ODBC 驱动程序管理器] 选项类型越界 (45)
 State HY092
Connected !                     //已经连接到数据库
Query Timeout is 0              //设置完查询超时为3秒后,查看查询超时的结果。连接access数据库的执行的结果是:
ODBC Version is: 3               //查询ODBC 版本的结果
Login Timeout is: 3              //查询登录超时的结果
Error Get Connection timeout -1  //设置连接超时为3秒时, 出错信息
Error [Microsoft][ODBC 驱动程序管理器] 选项类型越界 (45)
 State HY092
Connected !                     //已经连接到数据库
Error Set Query Timeout -1      //设置 查询超时为3秒时,出错信息
Error [Microsoft][ODBC 驱动程序管理器] 选项类型越界 (45)
 State HY092是我的程序问题,还是驱动不支持?

解决方案 »

  1.   

    // TimeoutTest.cpp : Defines the entry point for the console application.
    //#include "stdafx.h"#include "windows.h"//ODBC API
    #include <sql.h> 
    #include <sqlext.h>
    #include <odbcinst.h>#pragma comment(lib,"odbc32.lib")
    #pragma comment(lib,"OdbcCP32.Lib")int main(int argc, char* argv[])
    {
    SQLHENV  hEnv; // Handle ODBC environment
    SQLRETURN  nRet; // result of functions
    SQLHDBC  hDBC; // Handle connection
    SQLHSTMT  hStmt; // Handle Statement SQLUINTEGER  nTimeout = 3; // Timeout
    SQLCHAR  nVersion = 0; SQLCHAR pszSqlState[SQL_MAX_MESSAGE_LENGTH] = "";
    SQLCHAR pszErrorMsg[SQL_MAX_MESSAGE_LENGTH] = "";
    SQLINTEGER nNativeError = 0L;
    SQLSMALLINT nErrorMsg = 0;

    // 1. allocate Environment handle and register version 
    nRet = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&hEnv); if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error AllocHandle\n");
    return 0;
    } nRet = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_UINTEGER); 
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error SetEnv\n");
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
    }
    nRet = SQLGetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)&nVersion, SQL_IS_INTEGER, NULL);
    if ((nRet == SQL_SUCCESS) || (nRet == SQL_SUCCESS_WITH_INFO))
    {
    printf("ODBC Version is: %ld\n", nVersion);
    }
    else
    {
    printf("Error Get ODBC Version %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hEnv, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("Error %s (%d)\n State %s \n", pszErrorMsg, nErrorMsg, pszSqlState);
    }
    // 2. allocate connection handle, set timeout
    nRet = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDBC); 
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error AllocHDB %d\n", nRet);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
    } nRet = SQLSetConnectAttr(hDBC, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)nTimeout, SQL_IS_INTEGER);
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error SetConnectAttr %d\n", nRet);
    } nRet = SQLGetConnectAttr(hDBC, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_INTEGER, NULL);
    if ((nRet == SQL_SUCCESS) || (nRet == SQL_SUCCESS_WITH_INFO))
    {
    printf("Login Timeout is: %ld\n", nTimeout);
    }
    else
    {
    printf("Error Get Login Timeout %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("Error %s (%d)\n State %s \n", pszErrorMsg, nErrorMsg, pszSqlState);
    } nRet = SQLSetConnectAttr(hDBC, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)nTimeout, SQL_IS_INTEGER);
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error SetConnectAttr %d\n", nRet);
    } nRet = SQLGetConnectAttr(hDBC, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_INTEGER, NULL);
    if ((nRet == SQL_SUCCESS) || (nRet == SQL_SUCCESS_WITH_INFO))
    {
    printf("Connection timeout is: %ld\n", nTimeout);
    }
    else
    {
    printf("Error Get Connection timeout %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("Error %s (%d)\n State %s \n", pszErrorMsg, nErrorMsg, pszSqlState);
    }

    // 3. Connect to the datasource "test" 
    nRet = SQLConnect(hDBC, (SQLCHAR*) "mysql", SQL_NTS,
     (SQLCHAR*) "inumen", SQL_NTS,
     (SQLCHAR*) "inumen", SQL_NTS);
    /* nRet = SQLConnect(hDBC, (SQLCHAR*) "test", SQL_NTS,
     (SQLCHAR*) "Admin", SQL_NTS,
     (SQLCHAR*) "", SQL_NTS);*/
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error SQLConnect %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("%s (%d)\n", pszErrorMsg, nErrorMsg);
    SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
    } printf("Connected !\n"); nRet = SQLAllocHandle(SQL_HANDLE_STMT, hDBC, &hStmt);
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error AllocStatement %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("%s (%d)\n", pszErrorMsg, nErrorMsg);
    SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
    }
    nRet = SQLSetStmtAttr(hStmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)nTimeout, SQL_IS_UINTEGER);
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error Set Query Timeout %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("Error %s (%d)\n State %s \n", pszErrorMsg, nErrorMsg, pszSqlState);
    SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    SQLFreeHandle(SQL_HANDLE_STMT, hStmt);

    return 0;
    } nRet = SQLGetStmtAttr(hStmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_UINTEGER, NULL);
    if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
    {
    printf("Error Get Query Timeout %d\n", nRet);
    SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
    pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
    printf("Error %s (%d)\n State %s \n", pszErrorMsg, nErrorMsg, pszSqlState);
    }
    else
    {
    printf("Query Timeout is %d\n", nTimeout);
    } //............................. SQLFreeHandle(SQL_HANDLE_STMT, hStmt); SQLDisconnect(hDBC); SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

    return 0;
    }
      

  2.   

    昨天,我在一台ms sql server 7的机器上试了一下,发现程序运行基本正常,只是取连接超时时会出错。
    今天我改了一下,在连接到数据库后取连接超时,结果mysql取的结果是:31536000,查询超时依然是0。而access就不支持改属性,返回的状态是:HYC00。
    看样不是我程序的问题了。
    难得mysql不支持设置连接超时和查询超时?
      

  3.   

    我在mysql网站的bug列表中查到了,他们说只能等到5.1版的mysql出来之后才能解决这个问题。真是郁闷!