1. 程式人生 > >ODBC API開發教程1

ODBC API開發教程1

第 1 章        介紹... 2

第 2 章        ODBC API訪問資料庫... 2

2.1       ODBC簡要介紹... 2

2.1.1        在沒有ODBC以前... 2

2.1.2    ODBC介紹... 3

2.1.3    ODBC結構... 3

2.1.4    ODBC的一致性... 4

2.2       使用ODBC進行資料庫開發基本知識介紹... 4

2.2.1        建立ODBC DSN.. 4

2.2.2        使用ODBC所需要的檔案... 6

2.2.3    SQL語句執行方式介紹... 6

2.2.4        獲取SQL語句執行的結果... 7

2.2.5        程式執行的基本流程圖... 8

2.2.6        資料型別定義... 9

2.2.7    ODBC控制代碼... 11

2.3       為本章的例程建立DSN與資料庫表... 11

2.4       ODBC的基本功能介紹... 11

2.4.1        所需要了解的ODBC API 11

2.5       ODBC的其他功能介紹... 18

2.5.1    ODBC連線控制代碼的引數設定... 18

2.5.2    ODBC語句控制代碼的引數設定... 19

2.5.3    ODBC中使用可以滾動的游標... 20

2.5.4        儲存過程的執行與引數的繫結... 21

2.5.5    SQL的準備與執行... 28

2.5.6        通過列繫結獲取欄位資料... 30

2.5.7    ODBC中BLOB(Binary Large Object)欄位資料的處理... 31

2.5.8    ODBC對事務的支援... 34

2.5.9        多執行緒... 34

2.5.10      SQL語句的非同步執行... 34

第 3 章        結束語... 35

第 1 章                介紹
在文章的開頭做一個習慣性的介紹。

本文從2002年11月開始寫,基本上在2002年12月時完成,當時本來作為一本書的一個章節,後來由於某些原因沒有完成該書。這段時間將本文內容進行了一些整理,放在網上希望能夠給大家一些幫助。

本文的內容主要是關於ODBC 的功能,所有內容都與ODBC 3.X版本相容。

本文簡要介紹了ODBC的歷史和發展,也介紹了ODBC的基本的常用功能。大致包括:

l          使用ODBC進行資料庫連線

l          利用ODBC直接執行SQL語句

l          ODBC游標型別介紹

l          利用滾動游標或非滾動游標進行結果集查詢

l          儲存過程的呼叫與引數繫結

l          SQL語句的準備執行方式

l          BLOB資料欄位的查詢和修改

本文的資料庫利用了MS SQL Server,ODBC在使用時是與資料庫無關的所以所有例程都可以執行在其他資料庫上,例如Oracle。其實利用Access資料庫來進行練習也是可以的,但是由於Access不能支援儲存過程,所以我沒有使用Access資料庫。

由於例程程式碼沒有找到,所以沒有就沒有辦法提供,但是文中的程式碼都比較詳細而且有具體的解釋。

書中有很多錯誤和不足之處希望大家能夠容忍和包含,也歡迎來信指出。

第 2 章                ODBC API訪問資料庫
2.1    ODBC簡要介紹
2.1.1    在沒有ODBC以前
請允許我將那時候成為第二黑暗時代,第一黑暗時代是沒有資料庫的時代。

ODBC的出現結束了資料庫開發的無標準時代。在沒有ODBC以前不同的資料庫的開發所採用的標準是不統一的。一般來講不同的資料庫廠商都有自己的資料庫開發包,這些開發包支援兩種模式的資料庫開發:預編譯的嵌入模式(例如Oracle的ProC,SQL Server的ESQL)和API呼叫(例如Oracle的OCI)。

對於一個開發人員來講使用預編譯方式開發是極其痛苦的,我就有過這樣的經歷,所有的SQL語句要寫在程式內部,並且遵守一定的規則,然後由資料庫廠商的預編譯工具處理後形成C程式碼,最後由C編譯器進行編譯。預編譯的最大問題就在於無法動態的生成SQL語句,我想作為一個程式設計師是很難接受的。

接下來的是使用API進行開發,和預編譯相比算是前進了一大步。資料庫廠商提供了開發包,你通過各種API函式就可以連線資料庫,執行查詢、修改、刪除,操縱游標,執行儲存過程等。對於程式設計師來講有了更多的自由,而且可以建立自己的開發包。但是這一切的開發只能針對同一種資料庫。

Oracle的OCI是一個非常優秀的C語言開發包,在ODBC中就在很多地方參照了OCI的設計。

2.1.2    ODBC介紹
ODBC(Open Database Connectivity)是由微軟公司提出的一個用於訪問資料庫的統一介面標準,隨著客戶機/伺服器體系結構在各行業領域廣泛應用,多種資料庫之間的互連訪問成為一個突出的問題,而 ODBC成為目前一個強有力的解決方案。ODBC之所以能夠操作眾多的資料庫,是由於當前絕大部分資料庫全部或部分地遵從關係資料庫概念,ODBC看待這些資料庫時正是著眼了這些共同點。雖然支援眾多的資料庫,但這並不意味ODBC會變得複雜,ODBC是基於結構化查詢語言(SQL),使用SQL可大大簡化其應用程式設計介面(API),由於ODBC思想上的先進性,而且沒有同類標準或產品與之競爭,因而越來越受到眾多廠家和使用者的青睞。目前,ODBC已經成為客戶機/伺服器系統中的一個重要支援技術。

在1994年時ODBC有了第一個版本,這種名為Open Data Base Connection(開放式資料庫互連)的技術很快通過了標準化並且得到各個資料庫廠商的支援。ODBC在當時解決了兩個問題,一個是在Windows 平臺上的資料庫開發,另一個是建立一個統一的標準,只要資料廠商提供的開發包支援這個標準,那麼開發人員通過ODBC開發的程式可以在不同的資料庫之間自由轉換。這對開發人員來說的確值得慶賀。

ODBC參照了X/OpenData Management: SQL Call-Level Interface和ISO/ICE1995 Call-Level Interface標準,在ODBC版本3.X中已經完全實現了這兩個標準的所有要求。所以本書所有內容都基於ODBC 3.0以上版本。

最開始時支援ODBC的資料庫只有SQL Server,ACCESS,FoxPro,這些都時微軟的產品,他們能夠支援ODBC一點也不奇怪,但是那時候Windows的圖形介面已經成為了客戶端軟體最理想的載體,所以各大資料廠商也在不久後釋出了針對ODBC的驅動程式。

在Windows 3.X和Windows 95的時候ODBC並不作為系統的組成部分出現,使用前必須另行安裝。但到了Windows 98的時候,當你安裝好作業系統後,ODBC不需要另行安裝了,因為它已經成為了作業系統的一部分。這對很多拒絕ODBC的人來說又少了一個藉口。

作為一個程式設計師,至少是我,我實在找不出什麼理由不為ODBC歡呼。此外ODBC的結構很簡單和清晰,學習和了解ODBC的機制和開發方法對學習ADO等其他的資料庫訪問技術會有所幫助。

2.1.3    ODBC結構
圖2.1顯示了ODBC的結構。

ODBC <wbr>API開發教程1

圖2.1

應用程式(Application)

應用程式本身不直接與資料庫打交道,主要負責處理並呼叫ODBC函式,傳送對資料庫的SQL請求及取得結果。

驅動程式管理器(Driver Manager )

驅動程式管理器是一個帶有輸入程式的動態連結庫(DLL),主要目的是載入驅動程式,處理ODBC呼叫的初始化呼叫,提供ODBC呼叫的引數有效性和序列有效性。

驅動程式(Driver)

驅動程式是一個完成ODBC函式呼叫並與資料庫相互影響的DLL,這些驅動程式可以處理對於特定的資料的資料庫訪問請求。對於應用驅動程式管理器送來的命令,驅動程式再進行解釋形成自己的資料庫所能理解的命令。驅動程式將處理所有的資料庫訪問請求,對於應用程式來講不需要關注所使用的是本地資料庫還上網路資料庫。

2.1.4    ODBC的一致性
ODBC 介面的優勢之一為互操作性,程式設計員可以在不指定特定資料來源情況下建立ODBC應用程式。從應用程式角度方面,為了使每個驅動程式和資料來源都支援相同的 ODBC函式呼叫和SQL語句集,ODBC介面定義了一致性級別,即ODBC API一致性和ODBC SQL語法一致性。SQL一致性規定了對SQL語句語法的要求,而API一致性規定了驅動程式需要實現的ODBC函式。一致性級別通過建立標準功能集來幫助應用程式和驅動程式的開發者,應用程式可以很容易地確定驅動程式是否提供了所需的功能,驅動程式可被開發以支援應用程式選項,而不用考慮每個應用程式的特定請求。

2.2    使用ODBC進行資料庫開發基本知識介紹
2.2.1    建立ODBC DSN
DSN (Data Source Name)是用於指定ODBC與相關的驅動程式相對應的一個入口,所有DSN的資訊由系統進行管理,一般來講當應用程式要使用ODBC訪問資料庫時,就需要指定一個DSN以便於連線到一個指定的ODBC驅動程式。在控制面板中開啟ODBC管理器,回看到如圖2.2的介面。

ODBC <wbr>API開發教程1

圖2.2

DSN共分為三類:

l          使用者DSN:對當前登入使用者可見,只能夠用於當前計算機。

l          系統DSN:對當前系統上所有使用者可見,包括NT中的服務。

l          檔案DSN:DSN資訊存放在檔案中,對能夠訪問到該檔案的使用者可見。

一個使用Access資料庫的DSN中的資訊如下:

[ODBC]

DRIVER=Driver do Microsoft Access (*.mdb)

UID=admin

DefaultDir=C:\www.vchelp.net\DB

DBQ=C:\www.vchelp.net\DB\chat.mdb

對於檔案DSN來講這些資訊存放在檔案中,對於使用者DSN和系統DSN來講這些資訊存放在登錄檔內。你可以通過建立檔案DSN來檢視每種DSN對應的資訊內容。

下面的例子將告訴你如何新增一個SQL Server的DSN。

ODBC <wbr>API開發教程1

圖2.3

圖2.3中的四個步驟分別是:

l          選擇SQL Server作為驅動程式

l          輸入DSN名稱和SQL Server伺服器地址或別名

l          輸入使用者和口令進行連線

l          選擇預設資料庫並完成

2.2.2    使用ODBC所需要的檔案
你需要下面的檔案:

l          sql.h:包含有基本的ODBC API的定義。

l          sqlext.h:包含有擴充套件的ODBC的定義。

l          odbc32.lib:庫檔案。

這些檔案在VC6,VC7都已經隨開發工具提供了,不需要另外安裝。

此外所有的ODBC函式都以SQL開始,例如SQLExecute,SQLAllocHandle。

2.2.3    SQL語句執行方式介紹
在ODBC中SQL語句的執行方式分為兩種,直接執行和準備執行。

直接執行是指由程式直接提供SQL語句,例如:Select * from test_table並呼叫SQLExecDirect執行,準備執行是指先提供一個SQL語句並呼叫SQLPrepare,然後當語句準備好後呼叫 SQLExecute執行前面準備好的語句。準備執行多用於資料插入和資料刪除,在進行準備時將由ODBC驅動程式對語句進行分析,在實際執行時可以避免進行SQL語句分析所花費的時間,所以在進行大批量資料操作時速度會比直接執行有明顯改善。在後面的章節中我會詳細介紹準備執行與行列繫結與引數替換的用法。

2.2.4    獲取SQL語句執行的結果
對於SQL查詢語句,ODBC會返回一個游標,與游標對應的是一個結果集合(可以理解為一個表格)。開發人員利用游標來瀏覽所有的結果,你可以利用ODBC API函式移動游標,並且獲取當前游標指向的行的列欄位的數值。此外還可以通過游標來對游標當前所指向的資料進行修改,而修改會直接反映到資料庫中。

對於資料更新語句,如插入,刪除和修改,在執行後可以得到當前操作所影響的資料的行數。

2.2.5    程式執行的基本流程圖

ODBC <wbr>API開發教程1
圖2.4

圖2.4中是一個基本的使用ODBC API的一個流程,你現在並不理解上面所有的函式的作用,這沒有關係。但希望能夠通過這幅圖給你一個最初的映象,那就是使用ODBC API開發並不複雜。

2.2.6    資料型別定義
在使用ODBC開發時一個重要的問題就是資料轉換的問題,在ODBC中存在下面的幾類資料:

l          資料庫中SQL語言表達資料的型別

l          ODBC中表達資料的型別

l          C語言中表達資料的型別

在程式執行過程中資料需要經歷兩次轉換:C語言的資料或結構型別與ODBC的資料型別的轉換,ODBC與SQL間資料型別的轉換。所以ODBC所定義的資料型別起到了中間橋樑的作用,在ODBC的驅動程式呼叫自己的DBMS資料庫訪問介面時就需要對資料型別進行轉換。我們所需要關注的是C語言的資料型別和 ODBC資料型別間的轉換關係。

從下圖中可以看到ODBC中定義的資料型別和SQL語言中資料型別的對應關係,所以通過下表我們可以將ODBC和SQL語言間的資料一一對應,在後面的文字中我們不再區分ODBC資料型別和SQL語言資料型別。

 ODBC資料型別名稱  SQL語言資料型別名稱
 SQL_CHAR  CHAR(n)
 SQL_VARCHAR  VARCHAR(n)
 SQL_LONGVARCHAR  LONG VARCHAR
 SQL_WCHAR  WCHAR(n)
 SQL_WVARCHAR  VARWCHAR(n)
 SQL_WLONGVARCHAR  LONGWVARCHAR
 SQL_DECIMAL  DECIMAL(p,s)
 SQL_NUMERIC  NUMERIC(p,s)
 SQL_SMALLINT  SMALLINT
 SQL_INTEGER  INTEGER
 SQL_REAL  REAL
 SQL_FLOAT  FLOAT(p)
 SQL_DOUBLE  DOUBLE PRECISION
 SQL_BIT  BIT
 SQL_TINYINT  TINYINT
 SQL_BIGINT  BIGINT
 SQL_BINARY  BINARY(n)
 SQL_VARBINARY  VARBINARY(n)
 SQL_LONGVARBINARY  LONG VARBINARY
 SQL_TYPE_DATE[6]  DATE
 SQL_TYPE_TIME[6]  TIME(p)
 SQL_TYPE_TIMESTAMP[6]  TIMESTAMP(p)

SQL_GUID

 GUID

 圖2.5

使用C/C++語言開發,那麼必定會在與ODBC語言間存在資料的轉換的問題,因為ODBC所存在的一些資料型別在C語言中是不存在的。在ODBC以巨集定義的方式定義了C語言和ODBC中使用的資料型別:

 C語言資料型別名稱  ODBC 資料型別定義

C語言實際型別

 SQL_C_CHAR  SQLCHAR *  unsigned char *
 SQL_C_SSHORT[j]  SQLSMALLINT  short int
 SQL_C_USHORT[j]  SQLUSMALLINT  unsigned short int
 SQL_C_SLONG[j]  SQLINTEGER  long int
 SQL_C_ULONG[j]  SQLUINTEGER  unsigned long int
 SQL_C_FLOAT  SQLREAL  float
 SQL_C_DOUBLE  SQLDOUBLE, SQLFLOAT  double
 SQL_C_BIT  SQLCHAR  unsigned char
 SQL_C_STINYINT[j]  SQLSCHAR  signed char
 SQL_C_UTINYINT[j]  SQLCHAR  unsigned char
 SQL_C_SBIGINT  SQLBIGINT  _int64[h]
 SQL_C_UBIGINT  SQLUBIGINT  unsigned _int64[h]
 SQL_C_BINARY  SQLCHAR *  unsigned char *
 SQL_C_BOOKMARK[i]  BOOKMARK  unsigned long int[d]
 SQL_C_VARBOOKMARK  SQLCHAR *

unsigned char *

 SQL_C_TYPE_DATE[c]  SQL_DATE_STRUCT

struct tagDATE_STRUCT {
     SQLSMALLINT year;
     SQLUSMALLINT month;
     SQLUSMALLINT day;
} DATE_STRUCT;[a]

 SQL_C_TYPE_TIME[c]

SQL_TIME_STRUCT

 struct tagTIME_STRUCT {
     SQLUSMALLINT hour;
     SQLUSMALLINT minute;
     SQLUSMALLINT second;
} TIME_STRUCT;[a]
 SQL_C_TYPE_TIMESTAMP[c]

SQL_TIMESTAMP_STRUCT

struct tagTIMESTAMP_STRUCT {
     SQLSMALLINT year;
     SQLUSMALLINT month;
     SQLUSMALLINT day;
     SQLUSMALLINT hour;
     SQLUSMALLINT minute;
     SQLUSMALLINT second;
     SQLUINTEGER fraction;[b]
} TIMESTAMP_STRUCT;[a]

 SQL_C_NUMERIC

SQL_NUMERIC_STRUCT

 struct tagSQL_NUMERIC_STRUCT {
     SQLCHAR precision;
     SQLSCHAR scale;
     SQLCHAR sign[g];
     SQLCHAR val[SQL_MAX_NUMERIC_LEN];[e], [f]
} SQL_NUMERIC_STRUCT;
 SQL_C_GUID  SQLGUID  struct tagSQLGUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} SQLGUID;[k]

 圖2.6

所以在ODBC的開發過程中不要使用int , float 之類的C語言的實際型別來定義變數而應該使用ODBC定義的資料型別來定義變數,如:SQLINTEGER,SQLFLOAT。

2.2.7    ODBC控制代碼
ODBC中的控制代碼分為三類:環境控制代碼,資料庫連線控制代碼,SQL語句控制代碼。

通過圖2.4看出,在使用ODBC功能時必須先申請環境控制代碼,然後在環境控制代碼的基礎上建立資料庫連線,最後在資料連線的基礎上執行SQL語句。

2.3    為本章的例程建立DSN與資料庫表
為了後面的例子能夠順利執行,請建立一個名稱為“test”的DSN,並且使用下面的語句在資料庫中建立表和插入基本的資料,這個例子和以後的例子中我們使用SQL Server作為資料庫,你需要連線到SQL Server上執行下面的語句來建立表和插入資料。

Create table test_t1(iID int primary key , tmJoin datetime , szName varchar(40) ,fTall float );

Insert into test_t1 values(1, '2002-1-1 15:25' , 'user_1',1.56 );

Insert into test_t1 values(2, '2002-1-2 12:25' , 'user_2',1.53 );

Insert into test_t1 values(3, '2002-1-3 13:25' , 'user_3',1.76 );