ODBCAPI開(kāi)發(fā)教程_第1頁(yè)
ODBCAPI開(kāi)發(fā)教程_第2頁(yè)
ODBCAPI開(kāi)發(fā)教程_第3頁(yè)
ODBCAPI開(kāi)發(fā)教程_第4頁(yè)
ODBCAPI開(kāi)發(fā)教程_第5頁(yè)
已閱讀5頁(yè),還剩58頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、ODBC API開(kāi)發(fā)教程第 1 章介紹在文章的開(kāi)頭做一個(gè)習(xí)慣性的介紹。本文從2002年11月開(kāi)始寫(xiě),基本上在2002年12月時(shí)完成,當(dāng)時(shí)本來(lái)作為一本書(shū)的一個(gè)章節(jié),后來(lái)由于某些原因沒(méi)有完成該書(shū)。這段時(shí)間將本文內(nèi)容進(jìn)行了一些整理,放在網(wǎng)上希望能夠給大家一些幫助。本文的內(nèi)容主要是關(guān)于ODBC 的功能,所有內(nèi)容都與ODBC 3.X版本兼容。本文簡(jiǎn)要介紹了ODBC的歷史和發(fā)展,也介紹了ODBC的基本的常用功能。大致包括:使用ODBC進(jìn)行數(shù)據(jù)庫(kù)連接利用ODBC直接執(zhí)行SQL語(yǔ)句ODBC光標(biāo)類(lèi)型介紹利用滾動(dòng)光標(biāo)或非滾動(dòng)光標(biāo)進(jìn)行結(jié)果集查詢(xún)存儲(chǔ)過(guò)程的調(diào)用與參數(shù)綁定SQL語(yǔ)句的準(zhǔn)備執(zhí)行方式BLOB數(shù)據(jù)字段的查詢(xún)和

2、修改本文的數(shù)據(jù)庫(kù)利用了MS SQL Server,ODBC在使用時(shí)是與數(shù)據(jù)庫(kù)無(wú)關(guān)的所以所有例程都可以運(yùn)行在其他數(shù)據(jù)庫(kù)上,例如Oracle。其實(shí)利用Access數(shù)據(jù)庫(kù)來(lái)進(jìn)行練習(xí)也是可以的,但是由于Access不能支持存儲(chǔ)過(guò)程,所以我沒(méi)有使用Access 數(shù)據(jù)庫(kù)。由于例程代碼沒(méi)有找到,所以沒(méi)有就沒(méi)有辦法提供,但是文中的代碼都比較詳細(xì)而且有具體的解釋。書(shū)中有很多錯(cuò)誤和不足之處希望大家能夠容忍和包含,也歡迎來(lái)信指出。第 2 章 ODBC API訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)2.1 ODBC簡(jiǎn)要介紹2.1.1 在沒(méi)有ODBC以前請(qǐng)?jiān)试S我將那時(shí)候成為第二黑暗時(shí)代,第一黑暗時(shí)代是沒(méi)有數(shù)據(jù)庫(kù)的時(shí)代。ODBC的出現(xiàn)結(jié)束了數(shù)據(jù)庫(kù)開(kāi)發(fā)

3、的無(wú)標(biāo)準(zhǔn)時(shí)代。在沒(méi)有ODBC以前不同的數(shù)據(jù)庫(kù)的開(kāi)發(fā)所采用的標(biāo)準(zhǔn)是不統(tǒng)一的。一般來(lái)講不同的數(shù)據(jù)庫(kù)廠商都有自己的數(shù)據(jù)庫(kù)開(kāi)發(fā)包,這些開(kāi)發(fā)包支持兩種模式的數(shù)據(jù)庫(kù)開(kāi)發(fā):預(yù)編譯的嵌入模式(例如Oracle 的ProC,SQL Server的ESQL和API調(diào)用(例如Oracle的OCI。對(duì)于一個(gè)開(kāi)發(fā)人員來(lái)講使用預(yù)編譯方式開(kāi)發(fā)是極其痛苦的,我就有過(guò)這樣的經(jīng)歷,所有的SQL語(yǔ)句要寫(xiě)在程序內(nèi)部,并且遵守一定的規(guī)則,然后由數(shù)據(jù)庫(kù)廠商的預(yù)編譯工具處理后形成C代碼,最后由C編譯器進(jìn)行編譯。預(yù)編譯的最大問(wèn)題就在于無(wú)法動(dòng)態(tài)的生成SQL語(yǔ)句,我想作為一個(gè)程序員是很難接受的。接下來(lái)的是使用API進(jìn)行開(kāi)發(fā),和預(yù)編譯相比算是前進(jìn)

4、了一大步。數(shù)據(jù)庫(kù)廠商提供了開(kāi)發(fā)包,你通過(guò)各種API函數(shù)就可以連接數(shù)據(jù)庫(kù),執(zhí)行查詢(xún)、修改、刪除,操縱光標(biāo),執(zhí)行存儲(chǔ)過(guò)程等。對(duì)于程序員來(lái)講有了更多的自由,而且可以創(chuàng)建自己的開(kāi)發(fā)包。但是這一切的開(kāi)發(fā)只能針對(duì)同一種數(shù)據(jù)庫(kù)。Oracle的OCI是一個(gè)非常優(yōu)秀的C語(yǔ)言開(kāi)發(fā)包,在ODBC中就在很多地方參照了OCI的設(shè)計(jì)。2.1.2 ODBC介紹ODBC(Open Database Connectivity是由微軟公司提出的一個(gè)用于訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的統(tǒng)一界面標(biāo)準(zhǔn),隨著客戶(hù)機(jī)/服務(wù)器體系結(jié)構(gòu)在各行業(yè)領(lǐng)域廣泛應(yīng)用,多種數(shù)據(jù)庫(kù)之間的互連訪(fǎng)問(wèn)成為一個(gè)突出的問(wèn)題,而 ODBC成為目前一個(gè)強(qiáng)有力的解決方案。ODBC之所以能夠操

5、作眾多的數(shù)據(jù)庫(kù),是由于當(dāng)前絕大部分?jǐn)?shù)據(jù)庫(kù)全部或部分地遵從關(guān)系數(shù)據(jù)庫(kù)概念,ODBC看待這些數(shù)據(jù)庫(kù)時(shí)正是著眼了這些共同點(diǎn)。雖然支持眾多的數(shù)據(jù)庫(kù),但這并不意味ODBC會(huì)變得復(fù)雜,ODBC是基于結(jié)構(gòu)化查詢(xún)語(yǔ)言(SQL,使用SQL可大大簡(jiǎn)化其應(yīng)用程序設(shè)計(jì)接口(API,由于ODBC 思想上的先進(jìn)性,而且沒(méi)有同類(lèi)標(biāo)準(zhǔn)或產(chǎn)品與之競(jìng)爭(zhēng),因而越來(lái)越受到眾多廠家和用戶(hù)的青睞。目前,ODBC已經(jīng)成為客戶(hù)機(jī)/服務(wù)器系統(tǒng)中的一個(gè)重要支持技術(shù)。在1994年時(shí)ODBC有了第一個(gè)版本,這種名為Open Data Base Connection (開(kāi)放式數(shù)據(jù)庫(kù)互連的技術(shù)很快通過(guò)了標(biāo)準(zhǔn)化并且得到各個(gè)數(shù)據(jù)庫(kù)廠商的支持。ODBC在當(dāng)時(shí)

6、解決了兩個(gè)問(wèn)題,一個(gè)是在Windows 平臺(tái)上的數(shù)據(jù)庫(kù)開(kāi)發(fā),另一個(gè)是建立一個(gè)統(tǒng)一的標(biāo)準(zhǔn),只要數(shù)據(jù)廠商提供的開(kāi)發(fā)包支持這個(gè)標(biāo)準(zhǔn),那么開(kāi)發(fā)人員通過(guò)ODBC開(kāi)發(fā)的程序可以在不同的數(shù)據(jù)庫(kù)之間自由轉(zhuǎn)換。這對(duì)開(kāi)發(fā)人員來(lái)說(shuō)的確值得慶賀。ODBC參照了X/OpenData Management: SQL Call-Level Interface和ISO/ICE1995 Call-Level Interface標(biāo)準(zhǔn),在ODBC版本3.X中已經(jīng)完全實(shí)現(xiàn)了這兩個(gè)標(biāo)準(zhǔn)的所有要求。所以本書(shū)所有內(nèi)容都基于ODBC 3.0以上版本。最開(kāi)始時(shí)支持ODBC的數(shù)據(jù)庫(kù)只有SQL Server,ACCESS,FoxPro,這些都時(shí)微

7、軟的產(chǎn)品,他們能夠支持ODBC一點(diǎn)也不奇怪,但是那時(shí)候Windows的圖形界面已經(jīng)成為了客戶(hù)端軟件最理想的載體,所以各大數(shù)據(jù)廠商也在不久后發(fā)布了針對(duì)ODBC的驅(qū)動(dòng)程序。在Windows 3.X和Windows 95的時(shí)候ODBC并不作為系統(tǒng)的組成部分出現(xiàn),使用前必須另行安裝。但到了Windows 98的時(shí)候,當(dāng)你安裝好操作系統(tǒng)后,ODBC不需要另行安裝了,因?yàn)樗呀?jīng)成為了操作系統(tǒng)的一部分。這對(duì)很多拒絕ODBC的人來(lái)說(shuō)又少了一個(gè)借口。作為一個(gè)程序員,至少是我,我實(shí)在找不出什么理由不為ODBC歡呼。此外ODBC 的結(jié)構(gòu)很簡(jiǎn)單和清晰,學(xué)習(xí)和了解ODBC的機(jī)制和開(kāi)發(fā)方法對(duì)學(xué)習(xí)ADO等其他的數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)技

8、術(shù)會(huì)有所幫助。2.1.3 ODBC結(jié)構(gòu)圖2.1顯示了ODBC的結(jié)構(gòu)。 圖2.1應(yīng)用程序(Application應(yīng)用程序本身不直接與數(shù)據(jù)庫(kù)打交道,主要負(fù)責(zé)處理并調(diào)用ODBC函數(shù),發(fā)送對(duì)數(shù)據(jù)庫(kù)的SQL請(qǐng)求及取得結(jié)果。驅(qū)動(dòng)程序管理器(Driver Manager 驅(qū)動(dòng)程序管理器是一個(gè)帶有輸入程序的動(dòng)態(tài)鏈接庫(kù)(DLL,主要目的是加載驅(qū)動(dòng)程序,處理ODBC調(diào)用的初始化調(diào)用,提供ODBC調(diào)用的參數(shù)有效性和序列有效性。驅(qū)動(dòng)程序(Driver驅(qū)動(dòng)程序是一個(gè)完成ODBC函數(shù)調(diào)用并與數(shù)據(jù)庫(kù)相互影響的DLL,這些驅(qū)動(dòng)程序可以處理對(duì)于特定的數(shù)據(jù)的數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)請(qǐng)求。對(duì)于應(yīng)用驅(qū)動(dòng)程序管理器送來(lái)的命令,驅(qū)動(dòng)程序再進(jìn)行解釋形成

9、自己的數(shù)據(jù)庫(kù)所能理解的命令。驅(qū)動(dòng)程序?qū)⑻幚硭械臄?shù)據(jù)庫(kù)訪(fǎng)問(wèn)請(qǐng)求,對(duì)于應(yīng)用程序來(lái)講不需要關(guān)注所使用的是本地?cái)?shù)據(jù)庫(kù)還上網(wǎng)絡(luò)數(shù)據(jù)庫(kù)。2.1.4 ODBC的一致性O(shè)DBC 接口的優(yōu)勢(shì)之一為互操作性,程序設(shè)計(jì)員可以在不指定特定數(shù)據(jù)源情況下創(chuàng)建ODBC應(yīng)用程序。從應(yīng)用程序角度方面,為了使每個(gè)驅(qū)動(dòng)程序和數(shù)據(jù)源都支持相同的 ODBC函數(shù)調(diào)用和SQL語(yǔ)句集,ODBC接口定義了一致性級(jí)別,即ODBC API 一致性和ODBC SQL語(yǔ)法一致性。SQL一致性規(guī)定了對(duì)SQL語(yǔ)句語(yǔ)法的要求,而API一致性規(guī)定了驅(qū)動(dòng)程序需要實(shí)現(xiàn)的ODBC函數(shù)。一致性級(jí)別通過(guò)建立標(biāo)準(zhǔn)功能集來(lái)幫助應(yīng)用程序和驅(qū)動(dòng)程序的開(kāi)發(fā)者,應(yīng)用程序可以很容

10、易地確定驅(qū)動(dòng)程序是否提供了所需的功能,驅(qū)動(dòng)程序可被開(kāi)發(fā)以支持應(yīng)用程序選項(xiàng),而不用考慮每個(gè)應(yīng)用程序的特定請(qǐng)求。2.2 使用ODBC進(jìn)行數(shù)據(jù)庫(kù)開(kāi)發(fā)基本知識(shí)介紹2.2.1 建立ODBC DSNDSN (Data Source Name是用于指定ODBC與相關(guān)的驅(qū)動(dòng)程序相對(duì)應(yīng)的一個(gè)入口,所有DSN的信息由系統(tǒng)進(jìn)行管理,一般來(lái)講當(dāng)應(yīng)用程序要使用ODBC訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)時(shí),就需要指定一個(gè)DSN以便于連接到一個(gè)指定的ODBC驅(qū)動(dòng)程序。在控制面板中打開(kāi)ODBC管理器,回看到如圖2.2的界面。 圖2.2DSN共分為三類(lèi):1.用戶(hù)DSN:對(duì)當(dāng)前登錄用戶(hù)可見(jiàn),只能夠用于當(dāng)前計(jì)算機(jī)。2.系統(tǒng)DSN:對(duì)當(dāng)前系統(tǒng)上所有用戶(hù)可見(jiàn)

11、,包括NT中的服務(wù)。3.文件DSN:DSN信息存放在文件中,對(duì)能夠訪(fǎng)問(wèn)到該文件的用戶(hù)可見(jiàn)。一個(gè)使用Access數(shù)據(jù)庫(kù)的DSN中的信息如下:ODBCDRIVER=Driver do Microsoft Access (*.mdbUID=adminDefaultDir=C:DBDBQ=C:DBchat.mdb對(duì)于文件DSN來(lái)講這些信息存放在文件中,對(duì)于用戶(hù)DSN和系統(tǒng)DSN來(lái)講這些信息存放在注冊(cè)表內(nèi)。你可以通過(guò)創(chuàng)建文件DSN來(lái)查看每種DSN對(duì)應(yīng)的信息內(nèi)容。下面的例子將告訴你如何添加一個(gè)SQL Server的DSN。 圖2.3圖2.3中的四個(gè)步驟分別是:1.選擇SQL Server作為驅(qū)動(dòng)程序2.輸

12、入DSN名稱(chēng)和SQL Server服務(wù)器地址或別名3.輸入用戶(hù)和口令進(jìn)行連接4.選擇默認(rèn)數(shù)據(jù)庫(kù)并完成2.2.2 使用ODBC所需要的文件你需要下面的文件:sql.h:包含有基本的ODBC API的定義。sqlext.h:包含有擴(kuò)展的ODBC的定義。odbc32.lib:庫(kù)文件。這些文件在VC6,VC7都已經(jīng)隨開(kāi)發(fā)工具提供了,不需要另外安裝。此外所有的ODBC函數(shù)都以SQL開(kāi)始,例如SQLExecute,SQLAllocHandle。2.2.3 SQL語(yǔ)句執(zhí)行方式介紹在ODBC中SQL語(yǔ)句的執(zhí)行方式分為兩種,直接執(zhí)行和準(zhǔn)備執(zhí)行。直接執(zhí)行是指由程序直接提供SQL語(yǔ)句,例如:Select * fro

13、m test_table 并調(diào)用SQLExecDirect執(zhí)行,準(zhǔn)備執(zhí)行是指先提供一個(gè)SQL語(yǔ)句并調(diào)用SQLPrepare,然后當(dāng)語(yǔ)句準(zhǔn)備好后調(diào)用SQLExecute執(zhí)行前面準(zhǔn)備好的語(yǔ)句。準(zhǔn)備執(zhí)行多用于數(shù)據(jù)插入和數(shù)據(jù)刪除,在進(jìn)行準(zhǔn)備時(shí)將由ODBC驅(qū)動(dòng)程序?qū)φZ(yǔ)句進(jìn)行分析,在實(shí)際執(zhí)行時(shí)可以避免進(jìn)行SQL語(yǔ)句分析所花費(fèi)的時(shí)間,所以在進(jìn)行大批量數(shù)據(jù)操作時(shí)速度會(huì)比直接執(zhí)行有明顯改善。在后面的章節(jié)中我會(huì)詳細(xì)介紹準(zhǔn)備執(zhí)行與行列綁定與參數(shù)替換的用法。2.2.4 獲取SQL語(yǔ)句執(zhí)行的結(jié)果對(duì)于SQL查詢(xún)語(yǔ)句,ODBC會(huì)返回一個(gè)光標(biāo),與光標(biāo)對(duì)應(yīng)的是一個(gè)結(jié)果集合(可以理解為一個(gè)表格。開(kāi)發(fā)人員利用光標(biāo)來(lái)瀏覽所有的結(jié)果,

14、你可以利用ODBC API 函數(shù)移動(dòng)光標(biāo),并且獲取當(dāng)前光標(biāo)指向的行的列字段的數(shù)值。此外還可以通過(guò)光標(biāo)來(lái)對(duì)光標(biāo)當(dāng)前所指向的數(shù)據(jù)進(jìn)行修改,而修改會(huì)直接反映到數(shù)據(jù)庫(kù)中。對(duì)于數(shù)據(jù)更新語(yǔ)句,如插入,刪除和修改,在執(zhí)行后可以得到當(dāng)前操作所影響的數(shù)據(jù)的行數(shù)。2.2.5 程序執(zhí)行的基本流程圖 圖2.4圖2.4中是一個(gè)基本的使用ODBC API的一個(gè)流程,你現(xiàn)在并不理解上面所有的函數(shù)的作用,這沒(méi)有關(guān)系。但希望能夠通過(guò)這幅圖給你一個(gè)最初的映象,那就是使用ODBC API開(kāi)發(fā)并不復(fù)雜。2.2.6 數(shù)據(jù)類(lèi)型定義在使用ODBC開(kāi)發(fā)時(shí)一個(gè)重要的問(wèn)題就是數(shù)據(jù)轉(zhuǎn)換的問(wèn)題,在ODBC中存在下面的幾類(lèi)數(shù)據(jù):數(shù)據(jù)庫(kù)中SQL語(yǔ)言表達(dá)

15、數(shù)據(jù)的類(lèi)型ODBC中表達(dá)數(shù)據(jù)的類(lèi)型C語(yǔ)言中表達(dá)數(shù)據(jù)的類(lèi)型在程序運(yùn)行過(guò)程中數(shù)據(jù)需要經(jīng)歷兩次轉(zhuǎn)換:C語(yǔ)言的數(shù)據(jù)或結(jié)構(gòu)類(lèi)型與ODBC的數(shù)據(jù)類(lèi)型的轉(zhuǎn)換,ODBC與SQL間數(shù)據(jù)類(lèi)型的轉(zhuǎn)換。所以O(shè)DBC所定義的數(shù)據(jù)類(lèi)型起到了中間橋梁的作用,在ODBC的驅(qū)動(dòng)程序調(diào)用自己的DBMS數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)接口時(shí)就需要對(duì)數(shù)據(jù)類(lèi)型進(jìn)行轉(zhuǎn)換。我們所需要關(guān)注的是C語(yǔ)言的數(shù)據(jù)類(lèi)型和 ODBC數(shù)據(jù)類(lèi)型間的轉(zhuǎn)換關(guān)系。從下圖中可以看到ODBC中定義的數(shù)據(jù)類(lèi)型和SQL語(yǔ)言中數(shù)據(jù)類(lèi)型的對(duì)應(yīng)關(guān)系,所以通過(guò)下表我們可以將ODBC和SQL語(yǔ)言間的數(shù)據(jù)一一對(duì)應(yīng),在后面的文字中我們不再區(qū)分ODBC數(shù)據(jù)類(lèi)型和SQL語(yǔ)言數(shù)據(jù)類(lèi)型。 圖2.5使用C/C+語(yǔ)言

16、開(kāi)發(fā),那么必定會(huì)在與ODBC語(yǔ)言間存在數(shù)據(jù)的轉(zhuǎn)換的問(wèn)題,因?yàn)镺DBC所存在的一些數(shù)據(jù)類(lèi)型在C語(yǔ)言中是不存在的。在ODBC以宏定義的方式定義了C語(yǔ)言和ODBC中使用的數(shù)據(jù)類(lèi)型: 圖2.6所以在ODBC的開(kāi)發(fā)過(guò)程中不要使用int , float 之類(lèi)的C語(yǔ)言的實(shí)際類(lèi)型來(lái)定義變量而應(yīng)該使用ODBC定義的數(shù)據(jù)類(lèi)型來(lái)定義變量,如:SQLINTEGER, SQLFLOAT。2.2.7 ODBC句柄ODBC中的句柄分為三類(lèi):環(huán)境句柄,數(shù)據(jù)庫(kù)連接句柄,SQL語(yǔ)句句柄。通過(guò)圖2.4看出,在使用ODBC功能時(shí)必須先申請(qǐng)環(huán)境句柄,然后在環(huán)境句柄的基礎(chǔ)上創(chuàng)建數(shù)據(jù)庫(kù)連接,最后在數(shù)據(jù)連接的基礎(chǔ)上執(zhí)行SQL語(yǔ)句。2.3 為

17、本章的例程創(chuàng)建DSN與數(shù)據(jù)庫(kù)表為了后面的例子能夠順利執(zhí)行,請(qǐng)創(chuàng)建一個(gè)名稱(chēng)為“test”的DSN,并且使用下面的語(yǔ)句在數(shù)據(jù)庫(kù)中創(chuàng)建表和插入基本的數(shù)據(jù),這個(gè)例子和以后的例子中我們使用SQL Server作為數(shù)據(jù)庫(kù),你需要連接到SQL Server上執(zhí)行下面的語(yǔ)句來(lái)創(chuàng)建表和插入數(shù)據(jù)。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

18、',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 ; 2.4 ODBC的基本功能介紹2.4.1 所需要了解的ODBC API2.4.1.1 SQLAllocHandle 創(chuàng)建ODBC句柄SQLRETURN SQLAllocHandle(SQLSMALLINT HandleType,SQLHANDLE I

19、nputHandle,SQLHANDLE * OutputHandlePtr;第一個(gè)參數(shù)HandleType的取值可以為:SQL_HANDLE_ENV:申請(qǐng)環(huán)境句柄。SQL_HANDLE_DBC:申請(qǐng)數(shù)據(jù)庫(kù)連接句柄。SQL_HANDLE_STMT:申請(qǐng)SQL語(yǔ)句句柄,每次執(zhí)行SQL語(yǔ)句都申請(qǐng)語(yǔ)句句柄,并且在執(zhí)行完成后釋放。第二個(gè)參數(shù)為輸入句柄,第三個(gè)參數(shù)為輸出句柄,也就是是你在第一參數(shù)指定的需要申請(qǐng)的句柄。根據(jù)1.2.7節(jié)的說(shuō)明,在使用ODBC功能時(shí)必須先申請(qǐng)環(huán)境句柄,然后在環(huán)境句柄的基礎(chǔ)上創(chuàng)建數(shù)據(jù)庫(kù)連接,最后在數(shù)據(jù)連接的基礎(chǔ)上執(zhí)行SQL語(yǔ)句。所以可能的調(diào)用方式有三種。SQLAllocHand

20、le(SQL_HANDLE_ENV,NULL,&hEnv;SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER SQL_OV_ODBC3, SQL_IS_INTEGER;SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&hDBC;SQLAllocHandle(SQL_HANDLE_STMT,hDBC,&hSTMT;請(qǐng)注意,在創(chuàng)建環(huán)境句柄后請(qǐng)務(wù)必調(diào)用:SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER SQL_OV_ODBC3, SQL_IS

21、_INTEGER;將ODBC設(shè)置成為版本3,否則某些ODBC API 函數(shù)不能被支持。2.4.1.2 ODBC API的返回值ODBC API的返回值定義為:SQLRETURN。在成功時(shí)返回值為:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO;在失敗時(shí)返回錯(cuò)誤代碼。一點(diǎn)需要注意的是如果ODBC返回值為:SQL_SUCCESS_WITH_INFO并不表明執(zhí)行完全成功,而是表明執(zhí)行成功但是帶有一定錯(cuò)誤信息。當(dāng)執(zhí)行錯(cuò)誤時(shí)ODBC返回的是一個(gè)錯(cuò)誤信息的結(jié)果集,你需要遍歷結(jié)果集合中所有行,這點(diǎn)和后面講到的查詢(xún)SQL語(yǔ)句執(zhí)行結(jié)果集的思路很類(lèi)似。在ODBC可以利用SQLGetDiagR

22、ec來(lái)得到錯(cuò)誤描述信息:SQLRETURN SQLGetDiagRec(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLCHAR * Sqlstate,SQLINTEGER * NativeErrorPtr,SQLCHAR * MessageText,SQLSMALLINT BufferLength,SQLSMALLINT * TextLengthPtr;RecNumber:指明需要得到的錯(cuò)誤狀態(tài)行,從1開(kāi)始逐次增大。Sqlstate,NativeErrorPtr,MessageText:返回錯(cuò)誤狀態(tài),錯(cuò)誤代碼和

23、錯(cuò)誤描述。BufferLength:指定MessageText的最大長(zhǎng)度。TextLengthPtr:指定返回的MessageText中有效的字符數(shù)。函數(shù)的返回值可能為:SQL_SUCCESS,SQL_SUCCESS_WITH_INFO,SQL_ERROR, SQL_INVALID_HANDLE, SQL_NO_DATA。在沒(méi)有返回錯(cuò)誤的情況下你需要反復(fù)調(diào)用此函數(shù),并順次增大RecNumber參數(shù)的值,直到函數(shù)返回SQL_NO_DATA,以得到所有的錯(cuò)誤描述。示例,得到STMT句柄上的錯(cuò)誤信息:SQLCHAR SqlState6,SQLStmt100,MsgSQL_MAX_MESSAGE_LE

24、NGTH;SQLINTEGER NativeError;SQLSMALLINT i, MsgLen;int i = 1;while (rc2 = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState,&NativeError, Msg, sizeof(Msg, &MsgLen != SQL_NO_DATA/顯示錯(cuò)誤的代碼i+;下面的函數(shù)來(lái)自MS文檔,用于顯示一個(gè)錯(cuò)誤的詳細(xì)情況,你可以在你的程序中直接使用:void ProcessLogMessages(SQLSMALLINT plm_handle_type,/出現(xiàn)錯(cuò)誤時(shí)所使用的ODB

25、C句柄類(lèi)型,取值為:SQL_HANDLE_ENV ,SQL_HANDLE_DBC ,SQL_HANDLE_STMTSQLHANDLE plm_handle, /出現(xiàn)錯(cuò)誤時(shí)所使用的ODBC句柄char *logstring, /標(biāo)題字符串int ConnInd /指明句柄是否為DBC句柄RETCODE plm_retcode = SQL_SUCCESS;UCHAR plm_szSqlStateMAXBUFLEN = "",plm_szErrorMsgMAXBUFLEN = ""SDWORD plm_pfNativeError = 0L;SWORD plm_

26、pcbErrorMsg = 0;SQLSMALLINT plm_cRecNmbr = 1;SDWORD plm_SS_MsgState = 0, plm_SS_Severity = 0;SQLINTEGER plm_Rownumber = 0;USHORT plm_SS_Line;SQLSMALLINT plm_cbSS_Procname, plm_cbSS_Srvname;SQLCHAR plm_SS_ProcnameMAXNAME, plm_SS_SrvnameMAXNAME;printf(logstring;while (plm_retcode != SQL_NO_DATA_FOUND

27、plm_retcode = SQLGetDiagRec(plm_handle_type, plm_handle, plm_cRecNmbr, plm_szSqlState, &plm_pfNativeError,plm_szErrorMsg, MAXBUFLEN - 1, &plm_pcbErrorMsg;/ Note that if the application has not yet made a/ successful connection, the SQLGetDiagField/ information has not yet been cached by ODBC

28、/ Driver Manager and these calls to SQLGetDiagField/ will fail.if (plm_retcode != SQL_NO_DATA_FOUND if (ConnInd plm_retcode = SQLGetDiagField(plm_handle_type, plm_handle, plm_cRecNmbr,SQL_DIAG_ROW_NUMBER, &plm_Rownumber,SQL_IS_INTEGER,NULL;plm_retcode = SQLGetDiagField(plm_handle_type, plm_handl

29、e, plm_cRecNmbr,SQL_DIAG_SS_LINE, &plm_SS_Line,SQL_IS_INTEGER,NULL;plm_retcode = SQLGetDiagField(plm_handle_type, plm_handle, plm_cRecNmbr,SQL_DIAG_SS_MSGSTATE, &plm_SS_MsgState,SQL_IS_INTEGER,NULL;plm_retcode = SQLGetDiagField(plm_handle_type, plm_handle, plm_cRecNmbr, SQL_DIAG_SS_SEVERITY,

30、 &plm_SS_Severity,SQL_IS_INTEGER,NULL;plm_retcode = SQLGetDiagField(plm_handle_type, plm_handle, plm_cRecNmbr, SQL_DIAG_SS_PROCNAME, &plm_SS_Procname,sizeof(plm_SS_Procname,&plm_cbSS_Procname;plm_retcode = SQLGetDiagField(plm_handle_type, plm_handle, plm_cRecNmbr, SQL_DIAG_SS_SRVNAME, &a

31、mp;plm_SS_Srvname,sizeof(plm_SS_Srvname,&plm_cbSS_Srvname;printf("szSqlState = %sn",plm_szSqlState;printf("pfNativeError = %dn",plm_pfNativeError; printf("szErrorMsg = %sn",plm_szErrorMsg;printf("pcbErrorMsg = %dnn",plm_pcbErrorMsg; if (ConnInd printf(&quo

32、t;ODBCRowNumber = %dn", plm_Rownumber;printf("SSrvrLine = %dn", plm_Rownumber;printf("SSrvrMsgState = %dn",plm_SS_MsgState; printf("SSrvrSeverity = %dn",plm_SS_Severity; printf("SSrvrProcname = %sn",plm_SS_Procname; printf("SSrvrSrvname = %snn",

33、plm_SS_Srvname; plm_cRecNmbr+; /Increment to next diagnostic record. / End while.2.4.1.3 SQLConnect 連接數(shù)據(jù)庫(kù)SQLRETURN SQLConnect(SQLHDBC ConnectionHandle,SQLCHAR * ServerName,SQLSMALLINT NameLength1,SQLCHAR * UserName,SQLSMALLINT NameLength2,SQLCHAR * Authentication,SQLSMALLINT NameLength3;ConnectionHa

34、nlde:為DBC句柄,也就是前面提到到利用: SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&hDBC;申請(qǐng)的句柄。ServerName:為ODBC的DSN名稱(chēng)。NameLength1:指明參數(shù)ServerName數(shù)據(jù)的長(zhǎng)度。UserName:數(shù)據(jù)庫(kù)用戶(hù)名。NameLength2:指明參數(shù)UserName數(shù)據(jù)的長(zhǎng)度。Authentication:數(shù)據(jù)庫(kù)用戶(hù)密碼。NameLength3:指明參數(shù)Authentication數(shù)據(jù)的長(zhǎng)度。關(guān)于ServerName,UserName,Authentication參數(shù)長(zhǎng)度可以直接指定也可以指定為SQL_NTS表明參數(shù)是以

35、NULL字符結(jié)尾。示例代碼:retcode = SQLConnect(hdbc, (SQLCHAR* "odbc_demo", SQL_NTS,(SQLCHAR* "user", SQL_NTS, (SQLCHAR* "password", SQL_NTS;2.4.1.4 SQLExecDirect 直接執(zhí)行SQL語(yǔ)句SQLRETURN SQLExecDirect(SQLHSTMT StatementHandle,SQLCHAR * StatementText,SQLINTEGER TextLength;StatementHandle

36、:SQL語(yǔ)句句柄,也就是前面提到的利用:SQLAllocHandle(SQL_HANDLE_STMT,hDBC,&hSTMT;申請(qǐng)的句柄。StatementText:SQL語(yǔ)句。TextLength:參數(shù)StatementText的長(zhǎng)度,可以使用SQL_NTS表示字符串以NULL 字符結(jié)尾。如果函數(shù)執(zhí)行成功,你將會(huì)得到一個(gè)結(jié)果集,否則將返回錯(cuò)誤信息。SQLExecDirect函數(shù)除可以執(zhí)行 Select 語(yǔ)句外,還可以執(zhí)行Insert,Update, Delete 語(yǔ)句,在執(zhí)行修改SQL語(yǔ)句后可以利用SQLRowCount 函數(shù)來(lái)得到被更新的記錄的數(shù)量。2.4.1.5 SQLFetch

37、 移動(dòng)光標(biāo)SQLRETURN SQLFetch(SQLHSTMT StatementHandle;在你調(diào)用SQLExecDirect執(zhí)行SQL語(yǔ)句后,你需要遍歷結(jié)果集來(lái)得到數(shù)據(jù)。StatementHandle是STMT句柄,此句柄必須是被執(zhí)行過(guò)。當(dāng)調(diào)用SQLFetch 函數(shù)后,光標(biāo)會(huì)被移動(dòng)到下一條記錄處,當(dāng)光標(biāo)移動(dòng)到記錄集的最后一條,函數(shù)將會(huì)返回SQL_NO_DATA。要遍歷所有的結(jié)果集可以利用下面的方法:while(SQL_NO_DATA != SQLFetch(hSTMT /移動(dòng)光標(biāo),一直到集合末尾/得到結(jié)果2.4.1.6 SQLGetData 得到光標(biāo)處的某列的值SQLRETURN SQ

38、LGetData(SQLHSTMT StatementHandle,SQLUSMALLINT ColumnNumber,SQLSMALLINT TargetType,SQLPOINTER TargetValuePtr,SQLINTEGER BufferLength,SQLINTEGER * StrLen_or_IndPtr;StatementHanlde:STMT句柄。ClumnNumber:列號(hào),以1開(kāi)始。TargetType:數(shù)據(jù)緩沖區(qū)(TargetValuePtr的C語(yǔ)言數(shù)據(jù)類(lèi)型,請(qǐng)參照?qǐng)D2.6。BufferLength:數(shù)據(jù)緩沖區(qū)(TargetValuePtr的長(zhǎng)度。StrLen_or

39、_IndPtr:返回當(dāng)前得到的字段的字節(jié)長(zhǎng)度。下面是通過(guò)SQLFetch和SQLGetData得到記錄集的例子:/假設(shè) SQL = SELECT CUSTID, NAME, PHONE FROM CUSTOMERSSQLINTEGER sCustIDSQLCHAR szName50, szPhone50;SQLINTEGER cbName, cbAge, cbBirthday;/用來(lái)保存得到的數(shù)據(jù)的長(zhǎng)度while (TRUE /循環(huán)得到所有行retcode = SQLFetch(hstmt;/移動(dòng)光標(biāo)if (retcode = SQL_ERROR | retcode = SQL_SUCCESS

40、_WITH_INFO printf(“error SQLFetchn”;if (retcode = SQL_SUCCESS | retcode = SQL_SUCCESS_WITH_INFO /*得到當(dāng)前光標(biāo)處每列的值 */SQLGetData(hstmt, 1, SQL_C_ULONG, &sCustID, 0, &cbCustID;/此處并沒(méi)有指明BufferLength參數(shù)的值,是因?yàn)閿?shù)據(jù)類(lèi)型是定長(zhǎng)的LONG型SQLGetData(hstmt, 2, SQL_C_CHAR, szName, 50, &cbName;SQLGetData(hstmt, 3, SQL_

41、C_CHAR, szPhone, 50,&cbPhone;printf(out, "%5d %s %s", sCustID, szName, szPhone; else break;SQLGetData的另一個(gè)用處就是用于得到一些變長(zhǎng)字段的實(shí)際長(zhǎng)度,例如VARCHAR 字段,TEXT字段。例如:SQLGetData(hstmt, 2, SQL_C_CHAR, szName, 0, &cbName;當(dāng)你將 BufferLength 參數(shù)置為0,則會(huì)在 StrLen_or_IndPtr 參數(shù)中返回字段的實(shí)際長(zhǎng)度。但請(qǐng)注意第四個(gè)參數(shù)必須是一個(gè)合法的指針,不能夠?yàn)镹

42、ULL。此外在得到字段的值時(shí)還存在一個(gè)數(shù)據(jù)類(lèi)型轉(zhuǎn)換的問(wèn)題,比如說(shuō)數(shù)據(jù)庫(kù)內(nèi)的字段類(lèi)型為:INTEGER,那么你可以使用SQL_C_INTEGER,SQL_C_CHAR,SQL_C_ULONG 數(shù)據(jù)類(lèi)型來(lái)得到該字段的值。圖2.7就說(shuō)明了所有可能存在的轉(zhuǎn)換關(guān)系。 圖2.7參考前面的圖2.5和圖2.6就可以看出ODBC可以在SQL的數(shù)據(jù)類(lèi)型和C的數(shù)據(jù)類(lèi)型間提供轉(zhuǎn)換。請(qǐng)注意我講解圖2.5時(shí)提到的時(shí)ODBC數(shù)據(jù)類(lèi)型和SQL語(yǔ)言數(shù)據(jù)類(lèi)型之間的對(duì)應(yīng)關(guān)系,而這里提到的是數(shù)據(jù)之間的轉(zhuǎn)換關(guān)系。圖中用圓點(diǎn)標(biāo)出的交叉點(diǎn)為允許的類(lèi)型轉(zhuǎn)換,其中實(shí)心圓點(diǎn)標(biāo)出的是默認(rèn)的數(shù)據(jù)轉(zhuǎn)換類(lèi)型,空心圓點(diǎn)標(biāo)出的是允許的數(shù)據(jù)轉(zhuǎn)換類(lèi)型(允許并不

43、表明一定可以,例如 Char類(lèi)型可以轉(zhuǎn)換為SQL_C_INTEGER,但是并不是總能成功,當(dāng)字符為123時(shí)可以轉(zhuǎn)換為整數(shù)123,而字符為odbc時(shí)就不能成功。例如數(shù)據(jù)庫(kù)中的Char,VarChar類(lèi)型默認(rèn)都是對(duì)應(yīng)SQL_C_CHAR類(lèi)型。你還可以看到所有的數(shù)據(jù)庫(kù)字段類(lèi)型都可以轉(zhuǎn)換為 SQL_C_CHAR類(lèi)型,例如整數(shù)123可以轉(zhuǎn)換為”123”,而浮點(diǎn)數(shù)1.23可以轉(zhuǎn)換為”1.23”,日期的2002年10月1日可以轉(zhuǎn)換為” 2002-10-1”。所以在初學(xué)ODBC并且對(duì)性能要求不是非常高時(shí)可以用字符類(lèi)型來(lái)得到數(shù)據(jù)庫(kù)字段的值,這樣做會(huì)比較方便。2.4.1.7 SQLNumResultCols 得到

44、結(jié)果集中列數(shù)SQLRETURN SQLNumResultCols(SQLHSTMT StatementHandle,SQLSMALLINT * ColumnCountPtr;StatementHandle:STMT句柄ColumnCountPtr:返回列數(shù)2.4.1.8 SQLDescribeCol 得到結(jié)果集中列的描述SQLRETURN SQLDescribeCol(SQLHSTMT StatementHandle,SQLSMALLINT ColumnNumber,SQLCHAR * ColumnName,SQLSMALLINT BufferLength,SQLSMALLINT * Name

45、LengthPtr,SQLSMALLINT * DataTypePtr,SQLUINTEGER * ColumnSizePtr,SQLSMALLINT * DecimalDigitsPtr,SQLSMALLINT * NullablePtr;StatementHandle:STMT句柄。ColumnNumber:需要得到的列的序號(hào),從1開(kāi)始計(jì)算。ColumnName:得到列的名稱(chēng)。BufferLength:指明ColumnName參數(shù)的最大長(zhǎng)度。NameLengthPtr:返回列名稱(chēng)的長(zhǎng)度。DataTypePtr:得到列的ODBC數(shù)據(jù)類(lèi)型,請(qǐng)參照?qǐng)D2.5。ColumnSizePtr:得到列的長(zhǎng)

46、度。DecimalDigitsPtr:當(dāng)該列為數(shù)字類(lèi)型時(shí)返回小數(shù)點(diǎn)后數(shù)據(jù)的位數(shù)。NullablePtr:指明該列是否允許為空值。2.4.1.9 SQLRowCount 執(zhí)行SQL語(yǔ)句后得到影響的行數(shù)SQLRETURN SQLRowCount(SQLHSTMT StatementHandle,SQLINTEGER * RowCountPtr;你可以通過(guò)SQLExecDirect執(zhí)行SQL語(yǔ)句來(lái)插入,修改和刪除數(shù)據(jù),在執(zhí)行插入,修改和刪除的SQL語(yǔ)句后就可以通過(guò)SQLRowCount函數(shù)來(lái)得到被影響的數(shù)據(jù)的行數(shù)。Insert into test_t1 values(4, '2002-1-4

47、 11:25' , 'user_4',1.86 ; 2.5 ODBC的其他功能介紹2.5.1 ODBC連接句柄的參數(shù)設(shè)置在上一小節(jié)中提到了 SQLSetConnectAttr 這個(gè)函數(shù),這里需要對(duì)這個(gè)函數(shù)進(jìn)行一些簡(jiǎn)單的講解,你可以通過(guò)調(diào)用 SQLSetConnectAttr 在數(shù)據(jù)庫(kù)連接建立或建立后設(shè)置連接的一些屬性。SQLSetConnectAttr的函數(shù)原型如下:SQLRETURN SQLSetConnectAttr(SQLHDBC ConnectionHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGE

48、R StringLength;ConnectionHandle:提供DBC連接句柄。Attribute:指定需要設(shè)置的屬性類(lèi)型,在這里設(shè)置為值SQL_ATTR_AUTOCOMMIT。ValuePtr:提供參數(shù)值。StringLength:指定參數(shù)的長(zhǎng)度,當(dāng)參數(shù)為整數(shù)是設(shè)置為SQL_IS_INTEGER,當(dāng)參數(shù)為字符串時(shí)設(shè)置為字符串長(zhǎng)度或者為SQL_NTS 。這里講一下常用的參數(shù)Attribute可能的取值和ValuePtr對(duì)應(yīng)的取值: 2.5.2 ODBC語(yǔ)句句柄的參數(shù)設(shè)置如同數(shù)據(jù)庫(kù)連接句柄一樣,語(yǔ)句句柄也可以設(shè)置參數(shù)。函數(shù)為:SQLRETURN SQLSetStmtAttr(SQLHSTMT

49、 StatementHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength;ConnectionHandle:提供STMT連接句柄。Attribute:指定需要設(shè)置的屬性類(lèi)型,在這里設(shè)置為值SQL_ATTR_AUTOCOMMIT。ValuePtr:提供參數(shù)值。StringLength:指定參數(shù)的長(zhǎng)度,當(dāng)參數(shù)為整數(shù)是設(shè)置為SQL_IS_INTEGER,當(dāng)參數(shù)為字符串時(shí)設(shè)置為字符串長(zhǎng)度或者為SQL_NTS 。這里講一下常用的參數(shù)Attribute可能的取值和ValuePtr對(duì)應(yīng)的取值: 2.5.3 ODBC中使

50、用可以滾動(dòng)的光標(biāo)2.5.3.1 ODBC光標(biāo)類(lèi)型從上面的函數(shù)SQLSetStmtAttr可以看到我們?cè)贠DBC中可以使用不同的光標(biāo)類(lèi)型,那么這些光標(biāo)之間有什么區(qū)別。向前光標(biāo):SQL_CURSOR_FORWARD_ONLY,光標(biāo)僅僅向前滾動(dòng)。靜態(tài)光標(biāo):SQL_CURSOR_STATIC,結(jié)果集的數(shù)據(jù)是靜態(tài)的,這就是說(shuō)明在執(zhí)行查詢(xún)后,返回的結(jié)果集的數(shù)據(jù)不會(huì)再改變,即使是有其他程序更新了數(shù)據(jù)庫(kù)中的記錄,結(jié)果集中的記錄也不會(huì)發(fā)生改變。動(dòng)態(tài)光標(biāo):SQL_CURSOR_DYNAMIC,在光標(biāo)打開(kāi)以后,當(dāng)結(jié)果集中的行所對(duì)應(yīng)的數(shù)據(jù)值發(fā)生變化時(shí),其變化能夠能夠反映到光標(biāo)所對(duì)應(yīng)的結(jié)果集上,這些變化包括:字段的修改

51、,添加,結(jié)果集中行的順序變化。但是請(qǐng)注意如果行別刪除則無(wú)法在當(dāng)前結(jié)果集中反映出,因?yàn)楸粍h除的行不再出現(xiàn)在當(dāng)前的結(jié)果集中。動(dòng)態(tài)光標(biāo)所對(duì)應(yīng)的結(jié)果集在數(shù)據(jù)發(fā)生變化時(shí)會(huì)被重建。例如,假設(shè)動(dòng)態(tài)光標(biāo)已獲取到了兩行,然后,另一應(yīng)用程序更新了這兩行中的一行,并刪除了另一行,如果動(dòng)態(tài)游標(biāo)再試圖獲取那些行,它將不能檢測(cè)已刪除的行(因?yàn)楫?dāng)前結(jié)果集中只有一行,但是不要利用這個(gè)辦法去檢測(cè)被刪除的行,因?yàn)槌霈F(xiàn)這種情況還可能是因?yàn)樾械臄?shù)據(jù)被改變后不能再滿(mǎn)足查詢(xún)條件,而是返回已更新行的新值。鍵集光標(biāo):SQL_CURSOR_KEYSET_DRIVEN,和上面的動(dòng)態(tài)光標(biāo)所不同的是鍵集光標(biāo)能夠檢測(cè)到行的刪除和修改,但是無(wú)法檢測(cè)到檢

52、測(cè)到行的添加和結(jié)果集順序變化。因?yàn)樵诠鈽?biāo)創(chuàng)建時(shí)就創(chuàng)建了整個(gè)結(jié)果集,結(jié)果集合中記錄和順序已經(jīng)被固定,這一點(diǎn)和靜態(tài)光標(biāo)一樣。所以鍵集光標(biāo)可以說(shuō)是一種介于靜態(tài)光標(biāo)和動(dòng)態(tài)光標(biāo)之間的光標(biāo)類(lèi)型。需要說(shuō)明的是并不是每個(gè)DBMS的ODBC驅(qū)動(dòng)程序都能夠支持所有的這幾種光標(biāo),具體情況可以通過(guò)SQLGetInfo 函數(shù)進(jìn)行查詢(xún)。2.5.3.2 利用可滾動(dòng)光標(biāo)進(jìn)行查詢(xún)前面介紹的SQLFetch函數(shù)只能夠讓光標(biāo)向前移動(dòng),但在很多時(shí)候我們需要光標(biāo)能夠前后移動(dòng)。我們需要利用另一個(gè)函數(shù)SQLFetchScroll,但是再這之前請(qǐng)利用SQLSetStmtAttr正確設(shè)置光標(biāo)類(lèi)型。SQLFetchScroll的原型如下:SQL

53、RETURN SQLFetchScroll(SQLHSTMT StatementHandle,SQLSMALLINT FetchOrientation,SQLINTEGER FetchOffset;與SQLFetch不同的是多了后面兩個(gè)參數(shù)。FetchOrientation:表明滾動(dòng)的方式,允許的值如下: FetchOffset:表明光標(biāo)滾動(dòng)的位置。光標(biāo)滾動(dòng)后,獲取數(shù)據(jù)的方法和SQLFetch相同。滾動(dòng)時(shí)如果指定的位置超出結(jié)果集區(qū)域會(huì)返回錯(cuò)誤。2.5.4 存儲(chǔ)過(guò)程的執(zhí)行與參數(shù)的綁定在ODBC中調(diào)用存儲(chǔ)過(guò)程需要遵守ODBC的約定,SQL語(yǔ)句的格式為:?=call procedure-name(p

54、arameter,parameter.在這里必須講解問(wèn)號(hào)在SQL語(yǔ)句中的作用,問(wèn)號(hào)在SQL語(yǔ)句中代表參數(shù)的含義,這個(gè)參數(shù)可以是作為輸入,也可以作為輸出或者是既輸入又輸出,參數(shù)在SQL語(yǔ)句執(zhí)行后進(jìn)行指定,后面的章節(jié)中會(huì)進(jìn)一步講解參數(shù)的用法。其中第一問(wèn)號(hào)的作用是取得存儲(chǔ)過(guò)程的返回值,在執(zhí)行的過(guò)程中必須將此參數(shù)綁定到某一個(gè)變量,在執(zhí)行結(jié)束后被綁定的變量中就會(huì)被賦值。后面的參數(shù)可以是在SQL語(yǔ)句中直接指定,例如: call insert_this ( 1 , myName 也可以利用參數(shù)來(lái)指定例如: call insert_this ( 1 , ? 參數(shù)的值會(huì)在SQL語(yǔ)句執(zhí)行的過(guò)程中進(jìn)行指定。執(zhí)行存儲(chǔ)

55、過(guò)程直接利用SQLExecDirect API 函數(shù)就可以了。但是存儲(chǔ)過(guò)程中很多時(shí)候會(huì)返回結(jié)果,這些結(jié)果必須用參數(shù)的形式才能夠得到,所以下面要介紹一下如何利用參數(shù)綁定的方法來(lái)得到存儲(chǔ)過(guò)程的返回值,此外利用參數(shù)綁定還可以動(dòng)態(tài)的向存儲(chǔ)過(guò)程提供參數(shù)。但是進(jìn)行參數(shù)綁定就需要使用另一個(gè)ODBC API:SQLRETURN SQLBindParameter(SQLHSTMT StatementHandle,SQLUSMALLINT ParameterNumber,SQLSMALLINT InputOutputType,SQLSMALLINT ValueType,SQLSMALLINT ParameterT

56、ype,SQLUINTEGER ColumnSize,SQLSMALLINT DecimalDigits,SQLPOINTER ParameterValuePtr,SQLINTEGER BufferLength,SQLINTEGER * StrLen_or_IndPtr;StatementHandle:執(zhí)行SQL語(yǔ)句STMT句柄。ParameterNumber:指明要將變量與第幾個(gè)參數(shù)綁定,從1開(kāi)始計(jì)算。InputOutputType:指明是輸入還是輸出參數(shù)??梢匀≈档姆秶鸀?SQL_PARAM_INPUT,SQL_PARAM_OUTPUT ,SQL_PARAM_INPUT_OUTPUT。Va

57、lueType:指明用于和參數(shù)綁定的C語(yǔ)言數(shù)據(jù)類(lèi)型。ParameterType:指明在存儲(chǔ)過(guò)程中ODBC數(shù)據(jù)類(lèi)型。ColumnSize:指明接收數(shù)據(jù)的寬度,對(duì)于字符串和結(jié)構(gòu)需要指明數(shù)據(jù)的寬度,而對(duì)于普通的變量如SQLINTEGER,SQLFLOAT等設(shè)置為0就可以了。DecimalDigits :當(dāng)數(shù)據(jù)類(lèi)型為SQL_NUMERIC,SQL_DECIMAL時(shí)指明數(shù)字小數(shù)點(diǎn)的精度,否則填0。ParameterValuePtr:在作為輸入?yún)?shù)指明參數(shù)的指針,在作為輸出參數(shù)時(shí)指明接收數(shù)據(jù)的變量指針。BufferLength:指明參數(shù)指針?biāo)赶虻木彌_區(qū)的字節(jié)數(shù)大小。對(duì)于字符串和結(jié)構(gòu)需要指明大小,而對(duì)于普通的變量如SQLINTEGER,SQLFLOAT等設(shè)置為0就可以了。StrLen_or_IndPtr:作為輸入?yún)?shù)時(shí)指明數(shù)據(jù)的字節(jié)數(shù)大小,對(duì)于普通的定長(zhǎng)變量如SQLINTEGER,SQLFLOAT等設(shè)置為0就可以了,對(duì)于字符號(hào)串需要在此參數(shù)中指定字符串?dāng)?shù)據(jù)的長(zhǎng)度,或者設(shè)置為SQL_NULL_DATA表明此參數(shù)為空值,或者設(shè)置為SQL_NTS表明字符串以NULL字符結(jié)尾,對(duì)于結(jié)構(gòu)需要指明結(jié)構(gòu)的長(zhǎng)度。當(dāng)作為輸出參數(shù)時(shí),當(dāng)SQL執(zhí)行完畢后會(huì)在這個(gè)參數(shù)中返回拷貝的緩沖區(qū)的數(shù)據(jù)的字節(jié)數(shù)。2.5.4.1 例子一:調(diào)用含有輸出參數(shù)的存儲(chǔ)過(guò)程在S

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論