免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7148 | 回复: 6
打印 上一主题 下一主题

ODBC设置超时时遇到的非常奇怪的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-11-23 11:30 |只看该作者 |倒序浏览
我在项目中使用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

是我的程序问题,还是驱动不支持?

论坛徽章:
0
2 [报告]
发表于 2005-11-23 11:31 |只看该作者

程序代码



  1. // TimeoutTest.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"

  4. #include "windows.h"

  5. //ODBC API
  6. #include <sql.h>
  7. #include <sqlext.h>
  8. #include <odbcinst.h>

  9. #pragma comment(lib,"odbc32.lib")
  10. #pragma comment(lib,"OdbcCP32.Lib")

  11. int main(int argc, char* argv[])
  12. {
  13.         SQLHENV                         hEnv;                        // Handle ODBC environment
  14.         SQLRETURN                 nRet;                        // result of functions
  15.         SQLHDBC                         hDBC;                        // Handle connection
  16.         SQLHSTMT                 hStmt;                        // Handle Statement

  17.         SQLUINTEGER                 nTimeout = 3;        // Timeout
  18.         SQLCHAR                 nVersion = 0;

  19.         SQLCHAR pszSqlState[SQL_MAX_MESSAGE_LENGTH] = "";
  20.         SQLCHAR pszErrorMsg[SQL_MAX_MESSAGE_LENGTH] = "";


  21.         SQLINTEGER nNativeError = 0L;
  22.         SQLSMALLINT nErrorMsg = 0;
  23.        


  24.         // 1. allocate Environment handle and register version
  25.         nRet = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&hEnv);

  26.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  27.         {
  28.                 printf("Error AllocHandlen");
  29.                 return 0;
  30.         }

  31.         nRet = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_UINTEGER);
  32.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  33.         {
  34.                 printf("Error SetEnvn");
  35.                 SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  36.                 return 0;
  37.         }


  38.         nRet = SQLGetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)&nVersion, SQL_IS_INTEGER, NULL);
  39.         if ((nRet == SQL_SUCCESS) || (nRet == SQL_SUCCESS_WITH_INFO))
  40.         {
  41.                 printf("ODBC Version is: %ldn", nVersion);
  42.         }
  43.         else
  44.         {
  45.                 printf("Error Get ODBC Version %dn", nRet);
  46.                 SQLGetDiagRec(SQL_HANDLE_DBC, hEnv, 1,  pszSqlState, &nNativeError,
  47.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  48.                 printf("Error %s (%d)n State %s n", pszErrorMsg, nErrorMsg, pszSqlState);
  49.         }
  50.        

  51.         // 2. allocate connection handle, set timeout
  52.         nRet = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDBC);
  53.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  54.         {
  55.                 printf("Error AllocHDB %dn", nRet);
  56.                 SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  57.                 return 0;
  58.         }

  59.         nRet = SQLSetConnectAttr(hDBC, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)nTimeout, SQL_IS_INTEGER);
  60.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  61.         {
  62.                 printf("Error SetConnectAttr %dn", nRet);
  63.         }

  64.         nRet = SQLGetConnectAttr(hDBC, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_INTEGER, NULL);
  65.         if ((nRet == SQL_SUCCESS) || (nRet == SQL_SUCCESS_WITH_INFO))
  66.         {
  67.                 printf("Login Timeout is: %ldn", nTimeout);
  68.         }
  69.         else
  70.         {
  71.                 printf("Error Get Login Timeout %dn", nRet);
  72.                 SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
  73.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  74.                 printf("Error %s (%d)n State %s n", pszErrorMsg, nErrorMsg, pszSqlState);
  75.         }

  76.         nRet = SQLSetConnectAttr(hDBC, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)nTimeout, SQL_IS_INTEGER);
  77.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  78.         {
  79.                 printf("Error SetConnectAttr %dn", nRet);
  80.         }

  81.         nRet = SQLGetConnectAttr(hDBC, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_INTEGER, NULL);
  82.         if ((nRet == SQL_SUCCESS) || (nRet == SQL_SUCCESS_WITH_INFO))
  83.         {
  84.                 printf("Connection timeout is: %ldn", nTimeout);
  85.         }
  86.         else
  87.         {
  88.                 printf("Error Get Connection timeout %dn", nRet);
  89.                 SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
  90.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  91.                 printf("Error %s (%d)n State %s n", pszErrorMsg, nErrorMsg, pszSqlState);
  92.         }
  93.        
  94.         // 3. Connect to the datasource "test"
  95.         nRet = SQLConnect(hDBC, (SQLCHAR*) "mysql", SQL_NTS,
  96.                                                                          (SQLCHAR*) "inumen", SQL_NTS,
  97.                                                                          (SQLCHAR*) "inumen", SQL_NTS);
  98. /*        nRet = SQLConnect(hDBC, (SQLCHAR*) "test", SQL_NTS,
  99.                                                                          (SQLCHAR*) "Admin", SQL_NTS,
  100.                                                                          (SQLCHAR*) "", SQL_NTS);*/
  101.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  102.         {
  103.                 printf("Error SQLConnect %dn", nRet);
  104.                 SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
  105.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  106.                 printf("%s (%d)n", pszErrorMsg, nErrorMsg);
  107.                 SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
  108.                 SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  109.                 return 0;
  110.         }

  111.         printf("Connected !n");

  112.         nRet = SQLAllocHandle(SQL_HANDLE_STMT, hDBC, &hStmt);
  113.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  114.         {
  115.                 printf("Error AllocStatement %dn", nRet);
  116.                 SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
  117.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  118.                 printf("%s (%d)n", pszErrorMsg, nErrorMsg);
  119.                 SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
  120.                 SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  121.                 return 0;
  122.         }


  123.         nRet = SQLSetStmtAttr(hStmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)nTimeout, SQL_IS_UINTEGER);
  124.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  125.         {
  126.                 printf("Error Set Query Timeout %dn", nRet);
  127.                 SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
  128.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  129.                 printf("Error %s (%d)n State %s n", pszErrorMsg, nErrorMsg, pszSqlState);
  130.                 SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
  131.                 SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  132.                 SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
  133.                
  134.                 return 0;
  135.         }

  136.         nRet = SQLGetStmtAttr(hStmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_UINTEGER, NULL);
  137.         if ((nRet != SQL_SUCCESS) && (nRet != SQL_SUCCESS_WITH_INFO))
  138.         {
  139.                 printf("Error Get Query Timeout %dn", nRet);
  140.                 SQLGetDiagRec(SQL_HANDLE_DBC, hDBC, 1,  pszSqlState, &nNativeError,
  141.                                                 pszErrorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &nErrorMsg);
  142.                 printf("Error %s (%d)n State %s n", pszErrorMsg, nErrorMsg, pszSqlState);
  143.         }
  144.         else
  145.         {
  146.                 printf("Query Timeout is %dn", nTimeout);       
  147.         }

  148.         //.............................

  149.         SQLFreeHandle(SQL_HANDLE_STMT, hStmt);

  150.         SQLDisconnect(hDBC);

  151.         SQLFreeHandle(SQL_HANDLE_DBC, hDBC);
  152.         SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  153.        
  154.         return 0;
  155. }
复制代码

[ 本帖最后由 stavck 于 2005-11-23 15:46 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2005-11-23 15:33 |只看该作者
To lz:

以后发代码,麻烦用code标记,这样大家也好看一些。

对你的问题,我有几个疑问,希望你能讲清楚。

odbc大概有3个版本。每个版本支持的api是不一样的,所以,你首先要确定的是,你所使用的odbc驱动是否支持该api的调用,印象里SQLGetConnectAttr这个api,myODBC2.5就不支持。所以,你首先要做的是确定你所使用的odbc是哪一家的,他所提供的api属于odbc哪个版本的。

State HY092

这个就是它的状态信息,表示api不支持,你需要一本微软的odbc的手册。一般在mdac的文档里面就有,或者msdn里面也有。

论坛徽章:
0
4 [报告]
发表于 2005-11-23 15:41 |只看该作者
不好意思,我没有说清楚。
我使用的mysql的odbc驱动时3.51版,我到mysql的主页上查过,他们是支持这些函数的。
令我奇怪的是,access 的驱动竟然也连设置查询超时都不支持,以前写过ADO的代码,里面是可以设置查询超时的,所以很怀疑我的程序有问题。

我的代码是可以直接编译的,如果有兴趣,大家可以测试一下。

论坛徽章:
0
5 [报告]
发表于 2005-11-23 16:31 |只看该作者
你把
nRet = SQLGetConnectAttr(hDBC, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)&nTimeout, SQL_IS_INTEGER, NULL);
放到建立连接的SQLConnect后面去做,
我只记得当设置语句属性时,Set和Get的先后顺序有影响,连接超时这个属性对于连接是否建立的要求应当是可以在连接建立前后都可以的。但不知道这里为什么不行,你还是找个sql server试一下。

[ 本帖最后由 renstone921 于 2005-11-23 16:41 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2005-11-24 08:54 |只看该作者
谢谢renstone921!
昨天,我在一台ms sql server 7的机器上试了一下,发现程序运行基本正常,只是取连接超时时会出错。
今天我改了一下,在连接到数据库后取连接超时,结果mysql取的结果是:31536000,查询超时依然是0。而access就不支持改属性,返回的状态是:HYC00。
看样不是我程序的问题了。
难得mysql不支持设置连接超时和查询超时?

论坛徽章:
0
7 [报告]
发表于 2005-11-24 11:26 |只看该作者
我在mysql网站的bug列表中查到了,他们说只能等到5.1版的mysql出来之后才能解决这个问题。真是郁闷!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP