发新话题
打印

[转载]windowsODBC接口API+C实现对ACCESS库中所有表的遍历

[转载]windowsODBC接口API+C实现对ACCESS库中所有表的遍历

文章作者:板儿砖/heart
信息来源:进阶网(www.secrity.cn)
原始连接:http://www.secrity.cn/attackarc.asp?id=22


在网上搜了很长时间都没有结果,于是小弟细细研读MSDN得出此文,首先我们看一下实现此功能的核心函数

:SQLTables关于这个函数MSDN是这样描述的:
SQLTables returns the list of table, catalog, or schema names, and table types, stored in a

specific data source. The driver returns the information as a result set.

大概译为:SQLTables函数返回库中所有表名列表,目录,图式或名称,表类型,存放在一个特定的数据源中.

返回信息作为一个结果集进行访问.

函数的原型为:SQLRETURN SQLTables(
SQLHSTMTStatementHandle,
SQLCHAR *CatalogName,
SQLSMALLINTNameLength1,
SQLCHAR *SchemaName,
SQLSMALLINTNameLength2,
SQLCHAR *TableName,
SQLSMALLINTNameLength3,
SQLCHAR *TableType,
SQLSMALLINTNameLength4);


由此我们可以知道,只要对库的连接进行了初始化设置如,申请环境变量并设置,申请连接变量并设置,连接

库等.便可申请一个语句句柄来得到库中所有表名列表.



示例程序如下:
#include <windows.h>
#include <wchar.h>
#include <sqlext.h>//SQL常用函数及变量定义




typedef struct _ODBC_RS {
  SQLHSTMT hStmt;
  SQLSMALLINT  iCols;
  HGLOBAL lpstr[100];
  int iRows;
  int temp;
}ODBC_RS ;



BOOL Rs_Open(ODBC_RS * _strRs)
{
  SQLSMALLINT hret;
  int iCols;
  int iColLength,iPointLength,bNull,iDataType,iStrlength;
  char szColName[256];//列名返回值缓冲区。

  SQLNumResultCols((* _strRs).hStmt,&((* _strRs).iCols));
  if ((* _strRs).iCols<=0)
  {
    MessageBox(NULL,"无法得到结果集中的行数","erro!",MB_OK);
    return FALSE;
  }
  if((* _strRs).iCols>100)    //大于100列则取前100列
  {
    (* _strRs).iCols=100;
  }
  
  
  for(iCols=1;iCols<=(* _strRs).iCols;iCols++)
  {
    hret=SQLDescribeCol((* _strRs).hStmt,iCols,\
      szColName,sizeof(szColName),\
      &iColLength,&iDataType,\
      &iColLength,&iPointLength,&bNull);
    if (hret !=SQL_SUCCESS && hret !=SQL_SUCCESS_WITH_INFO)
  {
    MessageBox(NULL,TEXT("取得列属性时出错!"),TEXT("erro!"),MB_OK);
    return FALSE;
  }
   



    iColLength=iColLength*2+1;

    (* _strRs).lpstr[iCols]=GlobalAlloc(GPTR,iColLength);
    if((* _strRs).lpstr[iCols]==NULL)
    {
      MessageBox(NULL,"分配内存出错","erro!",MB_OK);
      return FALSE;
    }

    hret=SQLBindCol((* _strRs).hStmt,iCols,\
      SQL_C_CHAR,(* _strRs).lpstr[iCols],\
      iColLength,&iStrlength);
    if (hret !=SQL_SUCCESS && hret !=SQL_SUCCESS_WITH_INFO)
  {
    MessageBox(NULL,TEXT("取得列属性时出错!"),TEXT("erro!"),MB_OK);
    return FALSE;
  }
  }
  return TRUE;
}







int main(int argc,char * argv[])
{
  char a;
  HINSTANCE hInstance=GetModuleHandle(NULL);
  SQLSMALLINT hret;
  char sqlstr[1024];
  HINSTANCE hin;    //函数返回值
  SQLHENV hEnv;    //环境句柄
  SQLHDBC hDbc;    //连接句柄
  SQLHSTMT hStmt;
  int constr1len;
  char sqlstr1[1024];
  ODBC_RS rslist;

  if(argc<2 || (strstr(argv[1],".mdb")==NULL))
  {
    printf("erro!~");
    return 0;
  }
  wsprintf(sqlstr,"DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s",argv[1]);

    hret=SQLAllocHandle(SQL_HANDLE_ENV,NULL,&hEnv);  
    if (hret !=SQL_SUCCESS && hret !=SQL_SUCCESS_WITH_INFO)        

    //容错处理
    {
    MessageBox(NULL,TEXT("分配环境句柄进出现错误"),TEXT("erro!"),MB_OK);
    return 0;
    }
    hret=SQLSetEnvAttr(hEnv,SQL_ATTR_ODBC_VERSION,SQL_OV_ODBC3,0);      

  //设置环境句柄
    if (hret !=SQL_SUCCESS && hret !=SQL_SUCCESS_WITH_INFO)
    {
      MessageBox(NULL,TEXT("设置环境句柄时出现错误"),TEXT("erro!"),MB_OK);
        return 0;
    }
    hret=SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&hDbc);         

   
    if (hret !=SQL_SUCCESS && hret !=SQL_SUCCESS_WITH_INFO)
    {
      MessageBox(NULL,TEXT("分配连接句柄时出现错误"),TEXT("erro!"),MB_OK);
      return 0;
    }


   
    hret=SQLDriverConnect(hDbc,NULL,sqlstr,sizeof(sqlstr),\
                     

sqlstr1,sizeof(sqlstr1),&constr1len,\
                     

SQL_DRIVER_COMPLETE);
    printf("the complete connect string:%s",sqlstr1);
    hret=SQLAllocHandle(SQL_HANDLE_STMT,hDbc,&hStmt);  
              if (hret !=SQL_SUCCESS && hret !

=SQL_SUCCESS_WITH_INFO && hret!=SQL_NO_DATA)
              {
               
                MessageBox(NULL,TEXT("分配语

句句柄失败"),TEXT("erro!"),MB_OK);
                return 0;
              }
              hret=SQLSetStmtAttr

(hStmt,SQL_ATTR_CURSOR_TYPE,SQL_CURSOR_STATIC,0);   
              if (hret !=SQL_SUCCESS && hret !

=SQL_SUCCESS_WITH_INFO)
              {
                MessageBox(NULL,TEXT("设置语

句时出现错误"),\
                  TEXT

("erro!"),MB_OK);
                return 0;
              }

              hret=SQLTables

(hStmt,NULL,0,NULL,0,NULL,0,NULL,0);



              rslist.hStmt=hStmt;
              Rs_Open(&rslist);
              while(TRUE)
              {
                  hret=SQLFetchScroll

(rslist.hStmt,SQL_FETCH_NEXT,0);
                  
                  if

(hret==SQL_NO_DATA)
                  {
                        

RtlZeroMemory(rslist.lpstr[3],\
                        

                sizeof(rslist.lpstr[3]));  

  //清空缓冲区防止对下次操作的影响
                        

return 0;
                  }
                  printf("%10s%10s%

10s%10s\n",rslist.lpstr[1],rslist.lpstr[2],rslist.lpstr[3],rslist.lpstr[4]);  
                  RtlZeroMemory

(rslist.lpstr[3],\
                        

              sizeof(rslist.lpstr[3]));   

//清空缓冲区防止对下次操作的影响
                  rslist.iRows++;
              }
      scanf("%c",&a);
      SQLDisconnect(hDbc);
      SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
      SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
      return 0;
}
   





程序在windowsXPsp1+VC++6.0下调试通过,程序使用方法为:程序名 MDB文件完整路径(如在本目录可以不

是完整路径).

本人水平有限错误之处请大侠指正,QQ:283965069 欢迎交流

TOP

发新话题