ODBC访问数据库(转载)

使用ODBC API之前要用到的头文件和LIB库
#include "sql.h"              // This is the the main include for ODBC Core functions.
#include "sqlext.h"         // This is the include for applications using the Microsoft SQL Extensions
#include "sqltypes.h"    // This file defines the types used in ODBC
#include "sqlucode.h"   // This is the the unicode include for ODBC Core functions
#include "odbcss.h"      // This is the application include file for the SQL Server driver specific defines.
#pragma coment(lib, "odbc32.lib")

ODBC API的返回值
         ODBC API的返回值定义为:SQLRETURN。在成功时返回值为:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO;在失败时返回错误代码。一点需要注意的是如果ODBC返回值为:SQL_SUCCESS_WITH_INFO并不表明执行完全成功,而是表明执行成功但是带有一定错误信息。当执行错误时ODBC返回的是一个错误信息的结果集,你需要遍历结果集合中所有行,这点和后面讲到的查询SQL语句执行结果集的思路很类似。

SQLAllocHandle 创建ODBC句柄
        SQLRETURN SQLAllocHandle (
              SQL SMALLINT     HandleType,               // 需要申请的句柄类型
              SQLHANDLE          InputHandle,               // 输入句柄
              SQLHANDLE     *   OutputHandlePtr);     // 输出句柄,即在第一参数指定需要申请的句柄
        第一参数HandleType的取值可以为:
            1. SQL_HANDLE_ENV
            2. SQL_HANDLE_DBC
            3. SQL_HANDLE_STMT

SQLConnect 连接数据库
        SQLRETURN SQLConnect (
              SQLHDBC  ConnectionHandle,       // DBC句柄,hdbc
              SQLCHAR * ServerName,                // 为ODBC的DSN名称
              SQLSMALLINT NameLength1,      // 指明参数ServerName的长度(可以用SQL_NTS)
              SQLCHAR * UserName,                   // 数据库用户名
              SQLSMALLINT NameLength2,      // 指明参数UserName的长度(可以用SQL_NTS)
              SQLCHAR * Authentication,          // 数据库用户密码
              SQLSMALLINT NameLength3)      // 指明参数Authentication的长度(可以用SQL_NTS)
    例如:
        SQLConnect (
                hdbc,
                (SQLTCHAR*)szDSN, SQL_NTS,
                (SQLTCHAR*)szUserId, SQL_NTS,
                (SQLTCHAR*)szPassword, SQL_NTS);

SQLExecDirect 直接执行SQL语句
        SQLRETURN SQLExecDirect (
            SQLHSTMT      StatementHandle,      // STMT句柄
            SQLCHAR     *  StatementText,          // SQL语句
            SQLINTEGER    TextLength)              // 参数StatementText的长度,可以用SQL_NTS
        如果函数执行成功,你将会得到一个结果集,否则将返回错误信息。

获取SQL语句执行的结果
        对于SQL查询语句,ODBC会返回一个光标,与光标对应的是一个结果集合(可以理解为一个表格)。开发人员利用光标来浏览所有的结果,你可以利用ODBC API函数移动光标,并且获取当前光标指向的行的列字段的数值。此外还可以通过光标来对光标当前所指向的数据进行修改,而修改会直接反映到数据库中。

SQLFetch 移动光标
        SQLRETURN SQLFetch (SQLHSTMT StatementHandle);
        在你调用SQLExecDirect执行SQL语句后,你需要遍历结果集来得到数据。StatementHandle是STMT句柄,此句柄必须是被执行过。当调用SQLFetch 函数后,光标会被移动到下一条记录处,当光标移动到记录集的最后一条,函数将会返回SQL_NO_DATA。

 SQLGetData 得到光标处的某列的值
        SQLRETURN SQLGetData (
            SQLHSTMT              StatementHandlem,         // STMT句柄
            SQLUSMALLINT     ColumnNumber,              // 列号,以1开始
            SQLSMALLINT        TargetType,                    // 数据缓冲区(TargetValuePtr)的C语言类型
            SQLPOINTER            TargetValuePtr,              // 数据缓冲区
            SQLINTEGER            BufferLength,                 // 数据缓冲区(TargetValuePtr)的长度
            SQLINTEGER     *     StrLen_or_IndPtr);       // 返回当前字段得到的字节长度

SQLBindCol通过列绑定获得字段数据
        SQLRETURN SQLBindCol (
            SQLHSTMT              StatementHandle,          // STMT语句
            SQLUSMALLINT     ColumnNumber,            // 列号,以1开始
            SQLSMALLINT        TargetType,                   // 数据缓冲区(TargetValuePtr)的C语言类型
            SQLPOINTER            TargetValuePtr,             // 数据缓冲区
            SQLINTEGER             BufferLength,               // 数据缓冲区(TargetValuePtr)的字节长度
            SQLINTEGER     *     StrLen_or_IndPtr);      // 返回当前字段得到的字节长度
        在从结果集中读取字段值时可以利用SQLGetData,但为了速度可以利用列绑定(SQLBindCol)的方式,在每次移动光标后让ODBC将数据传送到指定的变量中

SQLNumResultCols 得到结果集中列数
        SQLRETURN SQLNumResultCols (
            SQLHSTMT           StatementHandle,   // STMT句柄
            SQLSMALLINT * ColumnCountPtr);  // 返回的列数

SQLRowCount 执行SQL语句后得到影响的行数
        SQLRETURN SQLRowCount (
            SQLHSTMT       StatementHandle,  // STMT句柄
            SQLINTEGER * RowCountPtr);       // 被影响的数据的行数
        你可以通过SQLExecDirect执行SQL语句来插入,修改和删除数据,在执行插入,修改和删除的SQL语句后就可以通过SQLRowCount函数来得到被影响的数据的行数。

SQLDescribeCol 得到结果集中列的描述
        SQLRETURN SQLDescribeCol (
            SQLHSTMT           StatementHandle,      // STMT句柄
            SQLSMALLINT    ColumnNumber,         // 需要得到的列的序号,从1开始计算
            SQLCHAR          * ColumnName,             // 得到列的名称
            SQLSMALLINT    BufferLength,             // 指明ColumnName参数的最大长度
            SQLSMALLINT * NameLengthPtr,         // 返回列名称的长度
            SQLSMALLINT * DataTypePtr,              // 返回列的ODBC数据类型,见表
            SQLUINTEGER  * ColumnSizePtr,           // 返回列的长度
            SQLSMALLINT * DecimalDigitsPtr,       // 当列为数字类型时返回小数点后数据的位数
            SQLSMALLINT * NullablePtr);               // 指明该列是否允许空值

SQLSetStmtAttr设置ODBC光标类型
        SQLRETURN SQLSetStmtAttr (
            SQLHSTMT     StatementHandle,     // STMT句柄
            SQLINTEGER  Attribute,                   // 指定需要设置的属性类型
            SQLPOINTER  ValuePtr,                    // 提供的参数值
            SQLINTEGER  StringLength);          // 指定参数的长度,当参数是整数时设置为
                                                // SQL_IS_INTEGER, 当参数是字符串是设置
                                                // 为字符串长度或者是SQL_NTS

函数SQLSetStmtAttr可以让我们在ODBC中可以使用不同的光标类型
Attribute
 ValuePtr
 作用
 
SQL_ATTR_ASYNC_ENABLE 整数,取值为:
SQL_ASYNC_ENABLE_OFF,
SQL_ASYNC_ENABLE_ON  是否使用异步执行功能
 
SQL_ATTR_QUERY_TIMEOUT 设置一个合法的整数 SQL语句执行时的超时秒数,设置为0表示无超时
 
SQL_ATTR_CURSOR_TYPE 整数,取值为:
SQL_CURSOR_FORWARD_ONLY,
SQL_CURSOR_STATIC,
SQL_CURSOR_DYNAMIC,SQL_CURSOR_KEYSET_DRIVEN 设置光标的类型
 
        1. 向前光标:SQL_CURSOR_FORWARD_ONLY,光标仅仅向前滚动。
        2. 静态光标:SQL_CURSOR_STATIC,结果集的数据是静态的,这就是说明在执行查询后,返回的结果集的数据不会再改变,即使是有其他程序更新了数据库中的记录,结果集中的记录也不会发生改变。
        3. 动态光标:SQL_CURSOR_DYNAMIC,在光标打开以后,当结果集中的行所对应的数据值发生变化时,其变化能够反映到光标所对应的结果集上,这些变化包括:字段的修改,添加,结果集中行的顺序变化。但是请注意如果行被删除则无法在当前结果集中反映出,因为被删除的行不再出现在当前的结果集中。动态光标所对应的结果集在数据发生变化时会被重建。例如,假设动态光标已获取到了两行,然后,另一应用程序更新了这两行中的一行,并删除了另一行,如果动态游标再试图获取那些行,它将不能检测已删除的行(因为当前结果集中只有一行,但是不要利用这个办法去检测被删除的行,因为出现这种情况还可能是因为行的数据被改变后不能再满足查询条件),而是返回已更新行的新值。
        4. 键集光标:SQL_CURSOR_KEYSET_DRIVEN,和上面的动态光标所不同的是键集光标能够检测到行的删除和修改,但是无法检测到行的添加和结果集顺序变化。因为在光标创建时就创建了整个结果集,结果集合中记录和顺序已经被固定,这一点和静态光标一样。所以键集光标可以说是一种介于静态光标和动态光标之间的光标类型。
        如:SQLSetStmtAttr (hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);

SQLFetchScroll利用可滚动光标进行查询
        SQLRETURN SQLFetchScroll (
            SQLHSTMT          StatementHandle,     // STMT语句
            SQLSMALLINT   FetchOrientation,     // 光标滚动的方式,见下表
            SQLINTEGER       FetchOffset);             // 光标滚动的位置
        前面介绍的SQLFetch函数只能够让光标向前移动,但在很多时候我们需要光标能够前后移动。我们需要利用另一个函数SQLFetchScroll,但是再这之前请利用SQLSetStmtAttr正确设置光标类型。
FetchOrientation
 含    义
 
SQL_FETCH_NEXT  滚动到下一行,这时候调用相当与SQLFetch,参数FetchOffset将被忽略(用0值)
SQL_FETCH_PRIOR 滚动到上一行,参数FetchOffset将被忽略(用0值)
SQL_FETCH_FIRST  滚动到第一行,参数FetchOffset将被忽略(用0值)
SQL_FETCH_LAST  滚动到最后一行,参数FetchOffset将被忽略(用0值)
SQL_FETCH_ABSOLUTE  滚动到参数FetchOffset指定的绝对行
SQL_FETCH_RELATIVE  由当前位置滚动到参数FetchOffset指定的相对行,FetchOffset大于0表示向前滚动,FetchOffset小于0表示向后滚动


使用C/C++语言开发,那么必定会在与ODBC语言间存在数据的转换的问题,因为ODBC所存在的一些数据类型在C语言中是不存在的。所以在ODBC的开发过程中不要使用int,float之类的C语言的实际类型来定义变量而应该使用ODBC定义的数据类型来定义变量,如SQLINTEGER,SQLFLOAT。在ODBC以宏定义的方式定义了C语言和ODBC中使用的数据类型:
C type identifier
 ODBC C typedef
 C type
 
SQL_C_CHAR
 SQLCHAR *
 unsigned char *
 
SQL_C_SSHORT
 SQLSMALLINT
 short int
 
SQL_C_USHORT
 SQLUSMALLINT
 unsigned short int
SQL_C_SLONG
 SQLINTEGER long int
SQL_C_ULONG
 SQLUINTEGER
 unsigned long int
SQL_C_FLOAT SQLREAL
 float
SQL_C_DOUBLE
 SQLDOUBLE, SQLFLOAT
 double
 
SQL_C_BIT SQLCHAR
 unsigned char
SQL_C_STINYINT SQLSCHAR
 signed char
 
SQL_C_UTINYINT
 SQLCHAR
 unsigned char
 
SQL_C_SBIGINT SQLBIGINT
 _int64
 
SQL_C_UBIGINT
 SQLUBIGINT
 unsigned _int64
 
SQL_C_BINARY
 SQLCHAR *
 unsigned char *
 
SQL_C_XML
 SQLCHAR *
 unsigned char *
SQL_C_BOOKMARK BOOKMARK unsigned long int
 
SQL_C_VARBOOKMARK SQLCHAR *
 unsigned char *
 
SQL_C_TYPE_DATE SQL_DATE_STRUCT
 struct tagDATE_STRUCT
{
        SQLSMALLINT        year;
        SQLUSMALLINT     month;
        SQLUSMALLINT     day;
} DATE_STRUCT;
SQL_C_TYPE_TIME
 SQL_TIME_STRUCT
 struct tagTIME_STRUCT
{
         SQLUSMALLINT hour;
         SQLUSMALLINT minute;
         SQLUSMALLINT second;
} TIME_STRUCT;
 
SQL_C_TYPE_TIMESTAMP
 SQL_TIMESTAMP_STRUCT
 struct tagTIMESTAMP_STRUCT
{
         SQLSMALLINT     year;
         SQLUSMALLINT  month;
         SQLUSMALLINT  day;
         SQLUSMALLINT  hour;
         SQLUSMALLINT  minute;
         SQLUSMALLINT  second;
         SQLUINTEGER      fraction;
} TIMESTAMP_STRUCT
 
SQL_C_NUMERIC
 SQL_NUMERIC_STRUCT struct tagSQL_NUMERIC_STRUCT
{
         SQLCHAR     precision;
         SQLSCHAR   scale;
         SQLCHAR     sign;
         SQLCHAR     val[SQL_MAX_NUMERIC_LEN];
} SQL_NUMERIC_STRUCT;
 
SQL_C_GUID
 SQLGUID
 struct tagSQLGUID {
        DWORD  Data1;
        WORD     Data2;
        WORD     Data3;
        BYTE        Data4[8];
} SQLGUID;
 
All C interval data types
 SQL_INTERVAL_STRUCT
 See the "C Interval Structure" section, later in this appendix.
 

posted @ 2008-01-15 13:59  shelvenn's blog  阅读(1209)  评论(0编辑  收藏  举报