天天看點

使用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.

http://tb.blog.csdn.net/TrackBack.aspx?PostId=241886