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