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