嵌套SQL语句訪问DB2中SQLCA的调用技巧
在程序中有針對(duì)性地對(duì)SQLCA實(shí)施調(diào)用,可對(duì)程序中各類SQL語句的執(zhí)行結(jié)果實(shí)施控制,從而避免程序的意外終止。同一時(shí)候,也能夠提高執(zhí)行效率,減小系統(tǒng)開銷和處理時(shí)間。本文將對(duì)此作一簡(jiǎn)要介紹。
SQLCA的結(jié)構(gòu)
SQLCA的結(jié)構(gòu)定義例如以下:
struc sqlca
{ ? ? ? ?unsigned char ? ? sqlcaid[8];
long ? ? ? ? ? ? ?sqlabc;
long ? ? ? ? ? ? ?sqlcode;
short ? ? ? ? ? ? sqlerrml;
unsigned char ? ? sqlerrnmc[10];
unsigned char ? ? sqlerrp[8];
long ? ? ? ? ? ? ?sqlerrd[6];
unsigned char ? ? sqlwarn[21];
unsigned char ? ? sqlstate[5]; ? ? ? ?}
結(jié)構(gòu)中各個(gè)域各有不同的含義和用途。部分域的功能和用途將在下面各小節(jié)中做具體探討,其他一些域的含義例如以下:
sqlcaid: ? ? ? ?標(biāo)識(shí)性域。包括字符串“sqlca”.
Sqlabc: ? ? ? ?包括sqlca結(jié)構(gòu)的長度。
Sqlerrml: ? ? ? ?包括sqlerrmc域中數(shù)據(jù)的實(shí)際長度。
Sqlerrmc: ? ? ? ? 由0或多個(gè)字串組成,它對(duì)返回的值給以一個(gè)更具體的解釋。如返回的代碼表示表沒找到,則此域中包括未找到的表名。
Sqlerrp: ? ? ? ? 包括一些對(duì)用戶沒用的論斷信息。
Sqlstate: ? ? ? ? 長度為5的字符串,它指示SQL語句的查詢結(jié)果。
與sqlca不同的是,它遵循ANSI/ISOSQL92的標(biāo)準(zhǔn),所以,雖然不同數(shù)據(jù)庫產(chǎn)品的sqlca結(jié)構(gòu)中sqlcode域的含義不同。但sqlstate域的含義是同樣的。
調(diào)用方法
DB2通過一個(gè)函數(shù):sqlaintp。能夠方便地讀取sqlca中SQL語句運(yùn)行后的結(jié)果和錯(cuò)誤。此函數(shù)定義在sql.h中,可通過下述語句實(shí)現(xiàn)對(duì)其定義:
EXEC SQL INCLUDE sqlca.h?
Sqlaintp函數(shù)格式例如以下:
int sqlaintp
( ? ? ? ?char ?*buffer
short ? buffer_size
short ? line_width
struct ?sqlca *sqlca ? ? ? ?)
當(dāng)中, buffer為存放了sqlca信息的緩沖區(qū);buffer_size中存放了buffer的長度;line_width存放了兩個(gè)運(yùn)行符之間的字符長度。
函數(shù)返回值為正時(shí)代表sqlca信息的長度,為負(fù)時(shí)代表沒有sqlca信息返回。一般來講,sqlca信息都可存放在長度為512個(gè)字節(jié)的緩沖區(qū)中。
為了處理各種錯(cuò)誤情況,DB2提供了WHENEVER語句。其詳細(xì)用法例如以下:
(1) ? ? ? ?EXEC SQL WHENEVER SQLERROR action ? ? ? SQLCODE<0時(shí),運(yùn)行action.
(2) EXEC SQL WHENEVER SQLWARNING action ? ? SQLCODE>;0但不為100且SQLWARN[0]=W時(shí)時(shí),運(yùn)行action.
(3) EXEC SQL WHENEVER NOT FOUND action ? ? ?SQLCODE=100時(shí),運(yùn)行action.
當(dāng)中action有兩種可能:
CONTINUE:繼續(xù)運(yùn)行程序中的還有一條命令。
GO TO label:轉(zhuǎn)到label指定的語句開始。
值得注意的是,WHENEVER語句的作用范圍到下一個(gè)WHENEVER時(shí)終止。
對(duì)SQLCODE的調(diào)用
? ?在對(duì)SQLCA的調(diào)用中,最常見的就是通過訪問SQLCODE來實(shí)現(xiàn)的。
非常多程序猿甚至在每條SQL語句運(yùn)行完成后都設(shè)置檢查SQLCODE返回值的代碼,以對(duì)程序的運(yùn)行進(jìn)行監(jiān)控。當(dāng)返回值為+0的時(shí)。表明SQL語句運(yùn)行成功。返回值為+100時(shí),表明滿足檢索條件的記錄沒找到。
一般來說。負(fù)的SQLCODE返回負(fù)值意味著SQL語句運(yùn)行失敗,程序猿可在程序中實(shí)現(xiàn)依據(jù)不同的SQLCODE返回值,採取不同的程序流程以實(shí)現(xiàn)錯(cuò)誤控制。比如。當(dāng)SQLCODE的返回值為-911時(shí), 表明系統(tǒng)檢測(cè)到了死鎖(Dead Lock),程序猿可針對(duì)這樣的情況採取下面兩種處置方法:
(1)設(shè)置循環(huán),重復(fù)運(yùn)行查詢請(qǐng)求并檢測(cè)SQLCODE,直至返回值為+0(運(yùn)行成功)。
(2)設(shè)置一個(gè)計(jì)數(shù)器,運(yùn)行查詢請(qǐng)求到一定次數(shù)后終止程序或向用戶發(fā)出警報(bào)。
值得注意的是,為了保證數(shù)據(jù)的完整性。有時(shí)須要針對(duì)返回的錯(cuò)誤類型對(duì)數(shù)據(jù)庫進(jìn)行回滾(ROLLBACK)操作,且回滾的起點(diǎn)不一定是未運(yùn)行成功的SQL語句導(dǎo)致系統(tǒng)所處于的狀態(tài)。回滾的起點(diǎn)與SQL語句的嵌套類型(動(dòng)態(tài),靜態(tài)。復(fù)合式)以及錯(cuò)誤類型都有關(guān)系。
尤其是后者,由于有些錯(cuò)誤類型會(huì)導(dǎo)致系統(tǒng)作一個(gè)隱式的回滾(比如SQLCODE -911),從而使回滾的起點(diǎn)推斷更為復(fù)雜。
? ?雖然多數(shù)情況下我們希望SQL語句運(yùn)行成功,但有些時(shí)候。通過一個(gè)有益“制造”的負(fù)的SQLCODE返回值,能夠使程序中的邏輯推斷更為簡(jiǎn)潔。還可在較大程度上降低系統(tǒng)開銷。我們能夠設(shè)想這樣一種情況:郵電局有兩種話費(fèi)收據(jù),一種是針對(duì)僅僅安有一部電話的用戶的,還有一種是針對(duì)安有多部電話的用戶的,兩種話費(fèi)收據(jù)上的項(xiàng)目個(gè)不同樣,須要不同的子程序進(jìn)行處理。在話費(fèi)收據(jù)處理程序中,首先依據(jù)每個(gè)用戶唯一的ID號(hào)檢索相應(yīng)的電話號(hào)碼。并設(shè)置計(jì)數(shù)器對(duì)檢索到的記錄數(shù)(安裝電話數(shù))進(jìn)行統(tǒng)計(jì),當(dāng)某用戶ID僅相應(yīng)一條電話號(hào)碼記錄時(shí)。調(diào)用單機(jī)用戶話費(fèi)收據(jù)處理程序?qū)ο鄳?yīng)用戶的話費(fèi)數(shù)據(jù)進(jìn)行處理;當(dāng)某用戶ID僅相應(yīng)多條電話號(hào)碼記錄時(shí),調(diào)用多機(jī)用戶話費(fèi)收據(jù)處理程序?qū)ο鄳?yīng)用戶的話費(fèi)數(shù)據(jù)進(jìn)行處理。不管何種情況。都需對(duì)用戶的數(shù)據(jù)又一次進(jìn)行讀取方可進(jìn)行下一步處理。也就是說,須要對(duì)一個(gè)用戶的電話數(shù)據(jù)進(jìn)行兩次讀取才干完畢相應(yīng)的數(shù)據(jù)處理。這無疑會(huì)極大的添加系統(tǒng)處理時(shí)間。
通過對(duì)SQLCODE的調(diào)用。能夠使這樣的情況得以顯著改善。首先。針對(duì)每個(gè)用戶的ID作一個(gè)SELECT操作,然后檢查SQLCODE返回值,當(dāng)返回值為+0時(shí),表明該用戶僅僅安裝了一部電話;當(dāng)返回值為-811時(shí)。表明該用戶安裝了不止一部電話。可由此推斷應(yīng)由那種程序來處理用戶話費(fèi)信息。採用這樣的解決方式,僅僅對(duì)用戶的數(shù)據(jù)讀取一次就可完畢用戶的話費(fèi)處理。差點(diǎn)兒降低了一半的系統(tǒng)處理時(shí)間。
與其他諸如改變表的結(jié)構(gòu)等方法。此種方法對(duì)系統(tǒng)的修改最小。而且簡(jiǎn)便易行。效果明顯。
? ?在對(duì)數(shù)據(jù)庫訪問的程序中,程序通常要求實(shí)現(xiàn)例如以下功能:更新數(shù)據(jù)庫中的某一條記錄,當(dāng)這條記錄不存在時(shí)創(chuàng)建對(duì)應(yīng)的記錄。
比較常見的做法是,先進(jìn)行一次SELECT查詢,當(dāng)SQLCODE返回+0時(shí),表明此條記錄已存在,然后再重讀此記錄對(duì)其進(jìn)行UPDATE操作;當(dāng)SQLCODE返回+100時(shí),表明對(duì)應(yīng)記錄不存在,接下來再進(jìn)行INSTER操作。還有一種實(shí)現(xiàn)方岸依據(jù)數(shù)據(jù)訪問的特點(diǎn),當(dāng)對(duì)數(shù)據(jù)的更新多于新值插入時(shí)。直接進(jìn)行UPDATE操作。當(dāng)SQLCODE返回+0時(shí)更新成功,反之。返回+100時(shí),需對(duì)其進(jìn)行INSERT操作。當(dāng)新值插入要多余于更新操作時(shí)。首先進(jìn)行INSERT操作。SQLCODE值為+0時(shí)插入成功,否則返回-803,表明原記錄已存在,須要進(jìn)行UPDATE操作。顯而易見,多數(shù)情況下,另外一種方法僅僅需對(duì)數(shù)據(jù)進(jìn)行一次操作就可以,從而提高系統(tǒng)的處理效率。
對(duì)SQLWARN的調(diào)用
? ?雖然程序猿通常總是忽略SQL的警告錯(cuò)誤。但適當(dāng)?shù)氖褂媚軌驇椭绦驒z測(cè)到各種潛在的錯(cuò)誤,而且能夠使編程更加簡(jiǎn)潔。
因此,此類警告信息亦應(yīng)受到程序猿的重視。
? ?警告信息在SQLCA中有兩種表示方法。
每個(gè)除了+100以外的SQLCODE正返回值都代表一定的警告信息;同一時(shí)候,SQLCA中的SQLWARN[n](n=1,2,3,4。5。6或A)返回值也代表著對(duì)應(yīng)的警告信息。當(dāng)系統(tǒng)發(fā)現(xiàn)警告錯(cuò)誤時(shí),系統(tǒng)會(huì)以這兩種方式通知程序。
此時(shí)。查詢可能會(huì)返回一些結(jié)果。但此時(shí)的結(jié)果極有可能是錯(cuò)誤或不完整的。當(dāng)SQLWARN[O]=W時(shí)。DB2提供了幫助用戶推斷詳細(xì)警告類型的信息,其對(duì)應(yīng)值及含義例如以下表:
SQLCA值 ? ? ? ?返回值 ? ? ? ?警告內(nèi)容
SQLWARN[1] ? ? ? ?W ? ? ? ?序主變量長度不夠而發(fā)生截取
SQLWARN[2] ? ? ? ?W ? ? ? ?字段功能處理的數(shù)據(jù)中有空(NULL)值
SQLWARN[3] ? ? ? ?W ? ? ? ?返回字段個(gè)數(shù)大于程序定義的序主變量個(gè)數(shù)
SQLWARN[4] ? ? ? ?W ? ? ? ?在UPDATE或DELETE操作中未指定WHERE條件
SQLWARN[6] ? ? ? ?W ? ? ? ?對(duì)時(shí)間數(shù)據(jù)進(jìn)行數(shù)學(xué)運(yùn)算后進(jìn)行修正
SQLWARN[A] ? ? ? ?W ? ? ? ?轉(zhuǎn)換出錯(cuò)
? ? ? ?如果某學(xué)校要計(jì)算某一學(xué)期各班。各科。個(gè)人的平均成績(jī)。
當(dāng)中。個(gè)人平均成績(jī)=(個(gè)人總分)/(本學(xué)期所學(xué)科目數(shù))。
因?yàn)楣ぷ魅藛T疏忽,誤將某一同學(xué)的學(xué)期學(xué)習(xí)科目輸為0。
在使用嵌套SQL語句的程序?qū)ο嚓P(guān)數(shù)據(jù)進(jìn)行處理時(shí),SQLCODE返回值為-802(除數(shù)為零)導(dǎo)致程序終止執(zhí)行。雖然用戶知道可能是某一項(xiàng)數(shù)據(jù)錯(cuò)誤,但無法知道詳細(xì)是哪一項(xiàng)數(shù)據(jù)錯(cuò)誤。對(duì)于一個(gè)擁有較多數(shù)據(jù)的學(xué)校來說,查找起來是非常費(fèi)事的。
通過下述辦法能夠非常好的解決這一問題:在定義代表計(jì)算結(jié)果的序主變量的同一時(shí)候,為其指定一個(gè)能夠?yàn)榭盏闹甘咀兞?#xff0c;如 :AVGRD :IND代表序主變量為AVGRD,指示變量為IND。此時(shí)發(fā)生被零除錯(cuò)誤時(shí),指示變量值被設(shè)為-2,同一時(shí)候SQLCODE返回值為+802警告信息。
程序捕捉到此信息時(shí),可向用戶提供對(duì)應(yīng)的信息,幫助用戶確定出錯(cuò)數(shù)據(jù)位置。
? ?當(dāng)SQLWARN[O]的值為W時(shí),表明系統(tǒng)檢測(cè)到警告錯(cuò)誤。此時(shí)系統(tǒng)提供的警告信息也可被程序猿所利用。比方:當(dāng)程序把一個(gè)表中的某一字符型字段值傳入一個(gè)比其長度要短的序主變量中時(shí),發(fā)生字符截取。雖然此時(shí)SQLCODE會(huì)返回+0,但程序獲取的數(shù)據(jù)是不完整的。通過為序主變量指定一個(gè)指示變量。發(fā)生相同錯(cuò)誤時(shí),SQLWARN[O]和SQLWARN[1]的返回值都為W。同一時(shí)候,指示變量被賦給了字段中數(shù)據(jù)的實(shí)際長度。此種方法甚至能夠用來推斷表中字段中字符串?dāng)?shù)據(jù)的實(shí)際長度。
對(duì)SQLERRD數(shù)組的調(diào)用
? ? SQLERRD是SQLCA中代表SQL查詢執(zhí)行結(jié)果的一個(gè)數(shù)組。數(shù)組中的不同元素有不同的含義。
當(dāng)中較經(jīng)常使用的是SQLERRD[3]。它將返回程序中上一次INSERT,UPDATE或DELETE操作所影響到的記錄數(shù)。否則。程序須要借助一定的循環(huán)來統(tǒng)計(jì)被以上操作影響到的記錄數(shù)。但值得注意的是。在執(zhí)行DELETE操作時(shí)。假設(shè)相關(guān)字段的刪除類型被設(shè)為CASCADE而導(dǎo)致被刪除其他記錄數(shù)不會(huì)被包括在內(nèi);同一時(shí)候,假設(shè)在DELETE語句中未指定WHERE條件,則SQLERRD[3]的返回值為-1。以上兩點(diǎn)在使用此數(shù)組時(shí)應(yīng)予以注意。SQLERRD中各元素的含義以及其對(duì)于復(fù)合式SQL語句。連接方法的不同含義例如以下:
SQLERRD元素 ? ? ? ?表示意義 ? ? ? ?復(fù)合式SQL語句 ? ? ? ?連接方式
SQLERRD[2] ? ? ? ?保存當(dāng)前SQL語句處理的行數(shù)。但若當(dāng)前SQL失敗, 則無定義; 若在數(shù)組操作中出錯(cuò), 則停于出錯(cuò)行, 這時(shí)給出成功處理的行數(shù); OPEN 運(yùn)行后, 清為0, FECTH 后增值(原有值+上本次fetch的行數(shù)); EXECUTE、INSERT、UPDATE、SELETE和SELECT后, 為成功處理的行數(shù)。
SQLERRD[3] ? ? ? ?返回的記錄數(shù)(預(yù)計(jì))及INSERT/UPDATE或DELETE操作所影響到的記錄數(shù)(不包括因限制條件而影響到的記錄) ? ? ? ? ? 總語句數(shù) ? ? ? ? 0:由底層客戶機(jī)的一段式提交托付確認(rèn)1:一段式提交2:一段式僅僅讀提交3:兩段式提交
SQLERRD[4] ? ? ? ?指出語句中出錯(cuò)的位移, 首字符位移為0。
SQLERRD[5] ? ? ? ?INSERT/UPDATE或DELETE操作所影響到的記錄數(shù)(包括因限制條件而影響到的記錄) ? ? ? ?因限制條件而影響到的記錄數(shù) ? ? ? ?無
經(jīng)常使用:SQLERRD[2] ?,如:#define SQLROWS sqlca.sqlerrd[2]
通過在程序中調(diào)用SQLCA。可對(duì)程序中嵌套的SQL語句的執(zhí)行結(jié)果進(jìn)行控制。增強(qiáng)了程序的可靠性。防止程序意外終止。也可使程序的編寫更加簡(jiǎn)潔。提高程序的執(zhí)行效率,縮短系統(tǒng)的處理時(shí)間。
轉(zhuǎn)載于:https://www.cnblogs.com/blfbuaa/p/6760722.html
總結(jié)
以上是生活随笔為你收集整理的嵌套SQL语句訪问DB2中SQLCA的调用技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [bzoj1934][Shoi2007]
- 下一篇: makefile笔记