將SQL嵌入到高級(jí)語(yǔ)言中混合編程,而程序中含有兩種不同計(jì)算模型的語(yǔ)句,一種是描述性的面向集合的SQL語(yǔ)句,一種是過(guò)程性的高級(jí)語(yǔ)言語(yǔ)句。兩種語(yǔ)言的分工是:SQL語(yǔ)句負(fù)責(zé)操縱數(shù)據(jù)庫(kù),高級(jí)語(yǔ)言語(yǔ)句負(fù)責(zé)控制程序流程。
它們之間的工作原理是:首先用SQL通信區(qū)(SQL Communication Area,簡(jiǎn)稱SQLCA)向主語(yǔ)言傳遞SQL語(yǔ)句的執(zhí)行狀態(tài)信息,使主語(yǔ)言能夠據(jù)此控制程序流程;在程序運(yùn)行中,主語(yǔ)言向SQL語(yǔ)句提供參數(shù),使用主變量(host variable)輸入數(shù)據(jù);同時(shí),程序把SQL語(yǔ)句查詢數(shù)據(jù)庫(kù)的結(jié)果交主語(yǔ)言進(jìn)一步處理,其中使用主變量和游標(biāo)(cursor)向主語(yǔ)言輸出數(shù)據(jù),從而實(shí)現(xiàn)了SQL語(yǔ)言的過(guò)程化工作。
一、SQL通信區(qū)的作用和定義
SQL語(yǔ)句執(zhí)行后,系統(tǒng)要反饋給應(yīng)用程序若干信息,主要包括描述系統(tǒng)當(dāng)前工作狀態(tài)和運(yùn)行環(huán)境的各種數(shù)據(jù),這些信息將送到SQL通信區(qū)SQLCA中。應(yīng)用程序從SQLCA中取出這些狀態(tài)信息,據(jù)此決定接下來(lái)執(zhí)行的語(yǔ)句。
SQLCA是一個(gè)數(shù)據(jù)結(jié)構(gòu)。
定義語(yǔ)句: EXEC SQL INCLUDE SQLCA
SQLCA中有一個(gè)存放每次執(zhí)行SQL語(yǔ)句后返回代碼的變量SQLCODE。應(yīng)用程序每執(zhí)行完一條SQL 語(yǔ)句之后都應(yīng)該測(cè)試一下SQLCODE的值,以了解該SQL語(yǔ)句執(zhí)行情況并做相應(yīng)處理。如果SQLCODE等于預(yù)定義的常量SUCCESS,則表示SQL語(yǔ)句成功,否則表示錯(cuò)誤代碼。
例如:在執(zhí)行刪除語(yǔ)句DELETE后,根據(jù)不同的執(zhí)行情況,SQLCA中有下列不同的信息:
· 違反數(shù)據(jù)保護(hù)規(guī)則,操作拒絕
· 沒(méi)有滿足條件的行,一行也沒(méi)有刪除
· 成功刪除,并有刪除的行數(shù)(SQLCODE=SUCCESS)
· 無(wú)條件刪除警告信息
· 由于各種原因,執(zhí)行出錯(cuò)
二、主變量的作用與使用方法
(1)主變量的作用
嵌入式SQL語(yǔ)句中可以使用主語(yǔ)言的程序變量來(lái)輸入或輸出數(shù)據(jù)。我們把在SQL語(yǔ)句中使用的主語(yǔ)言程序變量簡(jiǎn)稱為主變量。
主變量根據(jù)其作用的不同,分為輸入主變量和輸出主變量。
輸入主變量由應(yīng)用程序?qū)ζ滟x值,SQL語(yǔ)句引用;
輸出主變量由SQL語(yǔ)句對(duì)其賦值或設(shè)置狀態(tài)信息,返回給應(yīng)用程序。
一個(gè)主變量有可能既是輸入主變量又是輸出主變量。利用輸入主變量,我們可以指定向數(shù)據(jù)庫(kù)中插入的數(shù)據(jù),可以將數(shù)據(jù)庫(kù)中的數(shù)據(jù)修改為指定值,可以指定執(zhí)行的操作,可以指定WHERE子句或HAVING子句中的條件。利用輸出主變量,我們可以得到SQL語(yǔ)句的結(jié)果數(shù)據(jù)和狀態(tài)。
(2)指示變量
所謂指示變量是一個(gè)整型變量,用來(lái)“指示”所指主變量的值或條件。
一個(gè)主變量可以附帶一個(gè)任選的指示變量(Indicator Variable)。輸入主變量可以利用指示變量賦空值,輸出主變量可以利用指示變量檢測(cè)出是否空值,值是否被截?cái)唷?/p>
(3)主變量的說(shuō)明語(yǔ)句
說(shuō)明語(yǔ)句格式:
BEGIN DECLARE SECTION
<變量定義語(yǔ)句>
END DECLARE SECTION
*) 所有主變量和指示變量必須在上述格式中進(jìn)行說(shuō)明。說(shuō)明之后,主變量可以在SQL語(yǔ)句中任何一個(gè)能夠使用表達(dá)式的地方出現(xiàn);
*) 為了與數(shù)據(jù)庫(kù)對(duì)象名(表名、視圖名、列名等)區(qū)別,SQL語(yǔ)句中的主變量名前要加冒號(hào)(:)作為標(biāo)志。同樣,SQL語(yǔ)句中的指示變量前也必須加冒號(hào)標(biāo)志,并且要緊跟在所指主變量之后;而在SQL語(yǔ)句之外,主變量和指示變量均可以直接引用,不必加冒號(hào)。
三、游標(biāo)
(1)概念
一般情況下,SELECT語(yǔ)句查詢結(jié)果都是多條記錄,而主語(yǔ)言是面向記錄的,一組主變量一次只能存放一條記錄。
所以僅使用主變量并不能完全滿足SQL語(yǔ)句向應(yīng)用程序輸出數(shù)據(jù)的要求,為此嵌入式SQL引入了游標(biāo)的概念,用游標(biāo)來(lái)協(xié)調(diào)SQL語(yǔ)言與主語(yǔ)言這兩種不同的處理方式。即以游標(biāo)機(jī)制作為橋梁,將多條記錄一次一條送至宿主程序處理,從而把對(duì)集合的操作轉(zhuǎn)換為對(duì)單個(gè)記錄的處理。
“游標(biāo)”是系統(tǒng)為用戶開(kāi)設(shè)的一個(gè)數(shù)據(jù)緩沖區(qū),存放SQL語(yǔ)句的執(zhí)行結(jié)果。每個(gè)游標(biāo)區(qū)都有一個(gè)名字。用戶可以用SQL語(yǔ)句逐一從游標(biāo)中獲取記錄,并賦給主變量,交由主語(yǔ)言進(jìn)一步處理。
(2)游標(biāo)的使用方法
通常需要包括四個(gè)操作:
說(shuō)明游標(biāo)、打開(kāi)游標(biāo)、推進(jìn)游標(biāo)指針并取當(dāng)前記錄、關(guān)閉游標(biāo)。
詳細(xì)信息…
說(shuō)明游標(biāo):
用DECLARE語(yǔ)句為一條SELECT語(yǔ)句定義游標(biāo)。DECLARE語(yǔ)句的一般形式為:
EXEC SQL DECLARE <游標(biāo)名> CURSOR FOR <SELECT語(yǔ)句>;
其中SELECT語(yǔ)句可以是簡(jiǎn)單查詢,也可以是復(fù)雜的連接查詢和嵌套查詢。
定義游標(biāo)僅僅是一條說(shuō)明性語(yǔ)句,這時(shí)DBMS并不執(zhí)行SELECT指定的查詢操作。
打開(kāi)游標(biāo):
用OPEN語(yǔ)句將上面定義的游標(biāo)打開(kāi)。OPEN語(yǔ)句的一般形式為:
EXEC SQL OPEN <游標(biāo)名>;
打開(kāi)游標(biāo)實(shí)際上是執(zhí)行相應(yīng)的SELECT語(yǔ)句,把所有滿足查詢條件的記錄從指定表取到緩沖區(qū)中。這時(shí)游標(biāo)處于活動(dòng)狀態(tài),指針指向查詢結(jié)果集中第一條記錄。
推進(jìn)游標(biāo)指針并取當(dāng)前記錄:
用FETCH語(yǔ)句把游標(biāo)指針向前推進(jìn)一條記錄,同時(shí)將緩沖區(qū)中的當(dāng)前記錄取出來(lái)出來(lái)送至主變量供主語(yǔ)言進(jìn)一步處理。FETCH語(yǔ)句的一般形式為:
EXEC SQL FETCH <游標(biāo)名>
INTO <主變量>[<指示變量>][,<主變量>[<指示變量>]]...;
其中主變量必須與SELECT語(yǔ)句中的目標(biāo)列表達(dá)式具有一一對(duì)應(yīng)關(guān)系。
FETCH語(yǔ)句通常用在一個(gè)循環(huán)結(jié)構(gòu)中,通過(guò)循環(huán)執(zhí)行FETCH語(yǔ)句逐條取出結(jié)果集中的行進(jìn)行處理。
為進(jìn)一步方便用戶處理數(shù)據(jù),現(xiàn)在許多關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)對(duì)FETCH語(yǔ)句做了擴(kuò)充,允許用戶向任意方向以任意步長(zhǎng)移動(dòng)游標(biāo)指針,而不僅僅是把游標(biāo)指針向前推進(jìn)一行了。
關(guān)閉游標(biāo):
用CLOSE語(yǔ)句關(guān)閉游標(biāo),釋放結(jié)果集占用的緩沖區(qū)及其他資源。CLOSE語(yǔ)句的一般形式為:
EXEC SQL CLOSE <游標(biāo)名>;
游標(biāo)被關(guān)閉后,就不再和原來(lái)的查詢結(jié)果集相聯(lián)系。但被關(guān)閉的游標(biāo)可以再次被打開(kāi),與新的查詢結(jié)果相聯(lián)系。
綜合例子:給出帶有嵌入式SQL的一小段C程序。
詳細(xì)信息…
……
……
EXEC SQL INCLUDE SQLCA; ................(1) 定義SQL通信區(qū)
EXEC SQL BEGIN DECLARE SECTION; ........(2) 說(shuō)明主變量
CHAR title_id(7);
CHAR title(81);
INT royalty;
EXEC SQL END DECLARE SECTION;
main()
{
EXEC SQL DECLARE C1 CURSOR FOR ...(3) 游標(biāo)操作(定義游標(biāo))
SELECT tit_id, tit, roy FROM titles;
/* 從titles表中查詢 tit_id, tit, roy */
EXEC SQL OPEN C1; ..............(4) 游標(biāo)操作(打開(kāi)游標(biāo))
for(;;)
{
EXEC SQL FETCH C1 INTO :title_id, :title, :royalty;
...........(5) 游標(biāo)操作(推進(jìn)游標(biāo)指針)
(將當(dāng)前數(shù)據(jù)放入主變量)
if (sqlca.sqlcode <> SUCCESS)
....(6) 利用SQLCA中的狀態(tài)信息決定何時(shí)退出循環(huán)
break;
printf("Title ID: %s, Royalty: %d", :title_id, :royalty);
printf("Title: %s", :title);
/* 打印查詢結(jié)果 */
}
EXEC SQL CLOSE C1; ........(7) 游標(biāo)操作(關(guān)閉游標(biāo))
}