如果一个ODBC API函数执行成功,则返回SQL_SUCCESS或SQL_SUCCESS_WITH_INFO,SQL_SUCCESS指示可通过诊断记录获取有关操作的详细信息,SQL_SUCCESS_WITH_INFO指示应用程序执行结果带有警告信息,可通过诊断记录获取详细信息。如果函数调用失败,返回码为SQL_ERROR。

  1. SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);   1. 初始化环境变量   在CLI中有三个句柄,分别是环境句柄、连接句柄、语句句柄。在初始化过程中首先要对前两个句柄逐一进行获取,获取成功后可连接数据库并获取第三个句柄。  
1.  SQLRETURN ret;

   SQLHENV henv; // 环境句柄

   SQLHDBC hdbc; // 连接句柄

   SQLHSTMT hstmt; // 语句句柄

   SQLCHAR DBNAME[]="SAMPLE"; //数据库名

   SQLCHAR USERNAME[]="db2admin"; // 用户名

   SQLCHAR PSW[]="ibmdb2"; // 口令

   ret=SQLAllocEnv(&&henv) //分配环境句柄

   ret=SQLAllocConnect(henv,&&hdbc)

   //分配连接句柄

   ret=SQLSetConnectOption(hdbc,SQL_AUTOCOMMIT,SQL_AUTOCOMMIT_OFF)

   //设置连接属性

   ret=SQLConnect(hdbc,DBNAME,SQL_NTS,USERNAME,SQL_NTS,PSW,SQL_NTS) //连接数据库

   ret=SQLAllocStmt(hdbc,&&hstmt)

   //分配语句句柄

   上面的每个函数都有返回值,如果函数成功,ret值为SQL_SUCCESS,否则将返回错误代码。

   2. 语句的执行

   语句的执行分四个阶段:首先准备数据接收的缓冲区,然后执行准备好的SQL语句,第三步是将语句句柄和数据缓冲区进行绑定,最后获取数据。程序如下:

   char RowBuffer[100][200]; 

   //数据缓冲区,其大小可自定义

   typedef struct sqldat

   { SQLCHAR ColumnName[50];

    SQLSMALLINT BufferLength;

    SQLSMALLINT NameLength;

    SQLSMALLINT DataType;

    SQLUINTEGER ColumnSize;

    SQLSMALLINT FAR DecimalDigitsPtr;

    SQLSMALLINT FAR NullablePtr;

   } sqldata; 

   // 为第三步的绑定准备一个数据结构

   sqldata RowDesc[100];

   //用于绑定的变量,维数与缓冲区对应

   memset(RowBuffer,64,100 200); 

   //给缓冲区赋初始值,可以用于最后判断是否真正从数据库中获取了数据,这一步也可以省略

   char tempsql[100];

   sprintf(tempsql,"select NAME from db2admin.STAFF where ID= %s ",Condition);

   // Condition为变量值,可由用户输入

   sql=(SQLCHAR ) tempsql;

   ret=SQLPrepare(hstmt,sql,SQL_NTS)

   // 执行准备

   ret=SQLExecute(hstmt) // 执行

   执行成功后可进行绑定过程

   SQLINTEGER nullindicator;

   SQLINTEGER displaysize[MAX_COLUMN];

   SQLSMALLINT i;

   SQLSMALLINT num_columns;

   SQLNumResultCols(hstmt,&&num_columns); 

   //准备绑定用的相关变量

   for(i=1;i< =num_columns;i++)

    {

   RowDesc[i-1].BufferLength=200;

   SQLDescribeCol(hstmt,i, RowDesc[i-1].ColumnName,RowDesc[i-1].BufferLength,&&(RowDesc[i-1].NameLength),&&(RowDesc[i-1].DataType),&&(RowDesc[i-1].ColumnSize),RowDesc[i-1].DecimalDigitsPtr,RowDesc[i-1].NullablePtr);

   SQLColAttribute(hstmt,(SQLSMALLINT)(i),SQL_DESC_DISPLAY_SIZE,NULL,0,NULL,&&displaysize[i-1]);

   RowDesc[i-1].ColumnSize=max(displaysize[i-1],strlen((char )RowDesc[i-1].ColumnName))+1;

   SQLBindCol( hstmt, (SQLSMALLINT)i, 

   SQL_C_CHAR,(SQLPOINTER)(RowBuffer[i-1]),RowDesc[i-1].ColumnSize,

   &&nullindicator);

   }//循环绑定

   //绑定完成后,可以将数据读至缓冲区

   while(SQLFetch(hstmt)!=SQL_NO_DATA)

   {

   // SQLFetch函数将已经获取的数据存入缓冲区

   //此处的操作方式与ESQL中的游标类似,支持对结果集的操作

   //每执行一次SQLFetch函数会把当前获取的一行数据读到缓冲区中

   //RowBuffer[i]中将存放该行的第i 列数据值

   //本例中只有一行数据

   }

   char m_name[10];

   memcpy(m_name,RowBuffer[0],10);

   //从缓冲区中将结果读到用户变量中

   3. 释放环境变量

   在数据获取完成后,可以将环境变量释放掉,但要注意释放的先后顺序。

   SQLFreeStmt(hstmt,SQL_DROP); 

   // 释放语句句柄

   SQLDisconnect(hdbc);//与数据库断开

   SQLFreeConnect(hdbc);//释放连接句柄

   SQLFreeEnv(henv);//释放环境句柄

   经过上面的步骤,就完成了对数据库的读取过程。
 我的源码 测试成功了:
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <windows.h>
 #include <sql.h>
 #include <sqlext.h>
 #include <sqltypes.h>
 int main(){
     SQLRETURN ret;
     SQLHENV henv;
     SQLHDBC hdbc;
     SQLHSTMT hstmt;
     SQLCHAR * dsn,* username,* password,* sql;
     SQLSMALLINT dsn_len,username_len,password_len;
     SQLCHAR id[4],name[50];
     SQLINTEGER len;
     /*
     SQLSMALLINT * len;
     SQLCHAR * output;
     */
     ret=SQLAllocEnv(&henv);
     if(ret==SQL_SUCCESS){
          printf("环境分配成功!\n开始分配连接。。。\n");
          ret=SQLAllocConnect(henv,&hdbc); 
          if(ret==SQL_SUCCESS){
               printf("连接分配成功!\n"); 
               ret=SQLSetConnectOption(hdbc,SQL_AUTOCOMMIT,SQL_AUTOCOMMIT_OFF); 
               if(ret==SQL_SUCCESS){
                    printf("设置连接属性成功!\n开始连接数据库。。。\n");
                    dsn="sql2000";
                    username="admin";
                    password="123456";
                    dsn_len=strlen(dsn);
                    username_len=strlen(username);
                    password_len=strlen(password);
                    ret=SQLConnect(hdbc,dsn,dsn_len,username,username_len,password,password_len); 
                   /*
                    dsn="DRIVER={SQL Server};UID=admin;PWD=123456;DATABASE=tmsj008;SERVER=(local)";
                   
                    dsn="DRIVER={MySQL ODBC 5.0.22 Driver};SERVER=localhost;PORT=3306;OPTION=3;DATABASE=419;UID=root;PASSWORD=123456;";
                    
                    dsn="DRIVER=Microsoft Access Driver (*.mdb);DBQ=E:\\PHPnow\\htdocs\\myweb\\my.mdb;";
                    
                    dsn_len=strlen(dsn);
                    password_len=200;
                    username_len=100;
                    output=(SQLCHAR *)malloc(500*sizeof(SQLCHAR));
                    len=(SQLSMALLINT *)malloc(sizeof(SQLSMALLINT));
                    ret=SQLDriverConnect(hdbc,NULL,dsn,dsn_len,output,password_len,len,SQL_DRIVER_NOPROMPT);
                    */
                    if(ret==SQL_SUCCESS || ret==SQL_SUCCESS_WITH_INFO){
                         printf("连接成功!\n开始分配语句。。。\n"); 
                         ret=SQLAllocStmt(hdbc,&hstmt);
                         if(ret==SQL_SUCCESS){
                              printf("分配语句成功!\n开始执行语句。。。\n"); 
                              sql="select * from users";
                              ret=SQLExecDirect(hstmt,sql,SQL_NTS);
                              if(ret==SQL_SUCCESS){
                                  printf("执行语句成功!\n开始取出数据。。。\n"); 
                                  SQLBindCol(hstmt,1,SQL_CHAR,(SQLPOINTER)id,4,&len);
                                  SQLBindCol(hstmt,2,SQL_CHAR,(SQLPOINTER)name,50,&len); 
                                  while(SQLFetch(hstmt)==SQL_SUCCESS){
                                   printf("%s----%s\n",id,name);                                   
                                  }               
                              }else{
                                  printf("执行语句失败!"); 
                              }
                              SQLCloseCursor(hstmt);                
                         }else{
                              printf("分配语句失败!"); 
                         }
                    }else{
                         printf("连接失败!");    
                    }            
               }else{
                    printf("设置连接属性失败!");   
               } 
               SQLDisconnect(hdbc);
               SQLFreeConnect(hdbc);              
          }else{
             printf("连接分配错误!");   
          }
          SQLFreeEnv(henv);              
     }else{
         printf("环境分配错误!"); 
     }
     printf("\n关闭连接并且释放资源!");
     getch();
     return 0;
 }2. 
3. void*)SQL_OV_ODBC3,0);
4. 
5.  SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
6. 
7. sizeof(ConnStrOut),&ConnStrOutLen,SQL_DRIVER_NOPROMPT);
8. 
9. if(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){  
10. 
11. "ok"
12. 
13.  cout << ConnStrOutLen << endl;  
14. 
15.  cout << ConnStrOut << endl;  
16. 
17.  }

一般,编写ODBC程序主要有一下几个步骤:

    1、分配环境句柄:声明一个SQLHENV的变量,调用函数SQLAllocHandle。 设置环境属性:完成环境分配后,用函数SQLSetEnvAttr设置环境属性,注册ODBC版本号。 释放环境句柄:完成数据访问任务时,应调用SQLFreeHandle释放前面分配的环境。

    2、分配连接句柄:声明一个SQLHDBC类型的变量,调用SQLAllocHandle函数分配句柄。 设置连接属性:所有连接属性都可通过函数SQLSetConnectAttr设置,调用函数SQLGetConnectAttr可获取这些连接属性的当前设置值。

    3、连接数据源:对于不同的程序和用户接口,可以用不同的函数建立连接 SQLConnect:该函数只要提供数据源名称、用户ID和口令,就可以进行连接了。 SQLDriverConnect:该函数用一个连接字符串建立至数据源的连接,它可以让用户输入必要的连接信息,使用系统中还没定义的数据源。

服务器体系结构,因此本地数据库不支持该函数。

    4、准备并执行SQL语句     A、 分配语句句柄:语句句柄是通过调用SQLAllocHandle函数分配的。 函数SQLGetStmrrAttr和SQLSetStmrrAttr用来获取和设置一个语句句柄的选项,使用完,调用SQLFreeHandle释放该句柄。

    B、 执行SQL语句     SQLExecDirect:该函数直接执行SQL语句,对于只执行一次的SQL语句来说,该函数是执行最快的方法。

    SQLPrepare和SQLExecute:对于需要多次执行的SQL语句来说,可先调用SQLPrepare准备SQL语句的执行,用SQLExecute执行准备好的语句。

    C、 使用参数:使用参数可以使一条SQL语句多次执行,得到不同的结果。     函数SQLBindParameter负责为参数定义变量,将一段SQL语句中的一个参数标识符("?")捆绑在一起,实现参数值的传递。

    5、获取记录集

    A、   绑定列:首先必须分配与记录集中字段相对应的变量,然后通过函数SQLBindCol将记录字段同程序变量绑定在一起,对于长记录字段,可以通过调用函数SQLGetData直接取回数据。 绑定字段可以根据自己的需要全部绑定,也可以绑定其中的某几个字段。 通过调用函数SQLBindCol将变量地址值赋为NULL,可以结束对一个记录字段的绑定,通过调用函数SQLFreeStmt,将其中选项设为SQL_UNBIND,或者直接释放句柄,都会结束所有记录字段的绑定。

    B、SQLFetch:该函数用于将记录集的下一行变成当前行,并把所有捆绑过的数据字段的数据拷贝到相应的缓冲区。

    C、光标:应用程序获取数据是通过光标(Cursor)来实现的,在ODBC中,主要有3种类型的光标:单向光标、可滚动光标和块光标。

    有些应用程序不支持可滚动光标和块光标,ODBC SDK提供了一个光标库(ODBCCR32.DLL),在应用程序中可通过设置连接属性(SQL_STTR_ODBC_CURSOR)激活光标库。

    6、记录的添加、删除和更新:数据源数据更新可通过3种方式:通过SQLExecDirect函数使用相应的SQL语句;调用SQLSetPos函数实现记录集定义更新;调用SQLBulkOperations函数实现数据更新。

    第一种方式适用于任何ODBC数据源,后两种方式有的数据源不支持,可调用SQLGetInfo确定数据源。

    SQLBulkOperations:该函数操作基于当前行集,调用前,须先调用SQLFetch或SQLFetchScroll获取。

    函数调用后,块光标的位置变为未定义状况,因此,应该先调用函数SQLFetchScroll设定光标位置。

    7、错误处理:每个ODBC API函数都能产生一系列反映操作信息的诊断记录,可以用SQLGetDiagField函数获取诊断记录中特定的域,另外,可以使用SQLGetDiagRec获取诊断记录中一些常用的域。

   8、事务处理:事务提交有两种方式:自动提交模式和手动提交模式。应用程序可通过调用函数SQLSetConnectAttr设定连接属性SQL_ATTR_AUTOCOMMIT,自动提交模式是默认的连接属性设置,对于所有的ODBC驱动程序都能适应这种模式下,所有语句都是作为一个独立的事务进行处理的。 手动提交模式把一组SQL语句放入一个事务中,程序必须调用函数SQLEenTran明确地终止一个事务。若使用多个激活的事务,就必须建立多个连接,每一个连接包含一个事务。

    9、断开数据连接并释放环境句柄:完成数据库操作后,可调用SQLDisconnect函数关闭同数据库的连接。

http://hi.baidu.com/824766639/blog/item/d335bff41750a92dbc3109b1.html