纯C下用ODBC访问数据库(实例)

    最近有点发烧,想用DLL来做JSP……
    一天什么工作都没做,终于把它弄出来了,可是明天就惨了。
    取这么个名子就为了把大家骗来,呵呵。不过我确实努力做了,应该在纯C下能用吧,其实除了考二级我没用过纯C做过东西,我也不清楚这算不算纯C。
   
测试说明:
    1.在E盘下放一下名为ODBC.MDB的Access数据库。
    2.在这个数据库中建一个名为tips的表。
    3.表里面有三个字段,第一个字段是数字,后两个是字符串。
    因为sql.h、sqltypes.h、sqlext.h里面有很多类似ULONG的定义,
为了简单我加上了windef.h如果你允许windows.h的语那么在windows.h
里己经包含了windef.h我是为了尽一切努力少包含外部文件才这样做的。

    PS:另外还要确保你的IDE己经设置好ODBC了。我用的是Dev,在工程属性里设置了一个libodbc32.a的文件参数。如果没设置这个会出现一堆找不到符号的提示。别的IDE好像不一样,VC2008好像直接可以。

/**
   descript: 纯C下用ODBC访问数据库。
   date: 2008.4.9
   qq: 214395
**/

#ifndef _DOUDYA_C_ODBC_H
#define _DOUDYA_C_ODBC_H
/** 包含文件 **/
#include <windef.h>
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>

/** 简单的宏,用于判断ODBCAPI的执行结果是否正确 **/
#define isSuc(result) ((result) == SQL_SUCCESS || (result) == SQL_SUCCESS_WITH_INFO)

/** 可扩展设置 **/
char szConnectString[256] = "driver={Microsoft Access Driver (*.mdb)};DBQ=E://ODBC.MDB";
char szSQL[256] = "select * from `tips`";
/** 输出缓存 **/
char szDriverOutput[256];
short sDriverOutputLength;
/** 用于测试的变量 **/
int a = 0;
char b[255];
char c[255];
long temp = 0;

/** 用于测试的函数 **/
int main(){
    short sret; //返回代码
    void* henv;  //环境句柄
    void* hdbc;  //连接句柄
    long mode;//提交模式
    void* hsmt; //语句句柄
/** 申请环境句柄 **/
    sret = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
    if(!isSuc(sret))printf("申请环境句柄出错");
/** 设置环境属性,声明ODBC版本 **/
    sret = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,SQL_IS_INTEGER);
    if(!isSuc(sret))printf("声明ODBC版本出错");
/** 申请连接句柄 **/
    sret = SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
    if(!isSuc(sret))printf("申请连接句柄出错");
/** 设置连接属性 **/
    sret = SQLSetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,(void*)SQL_AUTOCOMMIT_OFF,SQL_IS_INTEGER);
    if(!isSuc(sret))printf("设置连接属性出错");
/** 取得连接属性 **/
    sret = SQLGetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,(void*)&mode,sizeof(mode) + 1,NULL);
    if(!isSuc(sret))printf("取得连接属性出错");
/** 连接数据源 **/
    sret = SQLDriverConnect(hdbc,NULL,(unsigned char *)szConnectString,SQL_NTS,(unsigned char *)szDriverOutput,256,&sDriverOutputLength,SQL_DRIVER_NOPROMPT);
    if(!isSuc(sret))printf("连接数据源出错");
/** 分配语句句柄 **/
    sret = SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hsmt);
    if(!isSuc(sret))printf("分配语句句柄出错");
/** 执行语句 **/
    sret = SQLExecDirect(hsmt,(SQLCHAR *)szSQL,SQL_NTS);
    if(!isSuc(sret))printf("执行语句出错");
/** 绑定结果集和获得数据 **/
/**
   小提示,这里应该可以先取得字段列表然后用循环做成自动邦定的。
**/
    SQLBindCol(hsmt,1,SQL_C_LONG,&a,sizeof(a),&temp);//测试时
    SQLBindCol(hsmt,2,SQL_C_CHAR,&b,sizeof(b),&temp);//测试时
    SQLBindCol(hsmt,3,SQL_C_CHAR,&c,sizeof(c),&temp);//测试时
/** 取得数据 **/
    while(true){
/** 滚动 **/
        sret = SQLFetchScroll(hsmt,SQL_FETCH_NEXT,0);
/**
前面如果发生错误,这里很可能得不到SQL_NO_DATA_FOUND而发生死循环,
所以我不用而用SQL_SUCCESS来判断,但这句在杂复的程序中里依然有用。
**/
        //if (sret == SQL_NO_DATA_FOUND) break; //如果没有数据就打断。
        if (sret != SQL_SUCCESS) break;
        printf("a = %d/r/n",a);//测试时
        printf("b = %s/r/n",b);//测试时
        printf("c = %s/r/n",c);//测试时
    }
/** 释放语句句柄 **/
    SQLFreeHandle(SQL_HANDLE_STMT,hsmt);
/** 提交连接的事务 **/
    SQLEndTran(SQL_HANDLE_DBC,hdbc,SQL_COMMIT);
/** 断开与数据源的连接 **/
    SQLDisconnect(hdbc);
/** 释放连接句柄 **/
    SQLFreeHandle(SQL_HANDLE_DBC,hdbc);
/** 释放环境句柄 **/
    SQLFreeHandle(SQL_HANDLE_ENV,henv);
/无关语句,仅仅是让程序停下来,看结果。
    getchar();//测试时
}

#endif
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值