| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 30. ecpg - 在 C 裡嵌入 SQL | Fast Forward | Next |
在 Section 30.4 裡你看到了如何從嵌入的 SQL 程序裡 執行 SQL 語句。那些語句有些只使用了固定的數值,並沒有提供一個插入 用戶提供的數值到語句中的方法,也沒有提供讓程序訪問查詢返回的數值的 方法。這種類型的語句在真正的應用中並不是很有用。本節詳細解釋如何在你的 C 程序和嵌入的 SQL 語句之間使用一種被稱作宿主變量 的機制傳遞數據。
在 C 程序和 SQL 語句之間傳遞數據在嵌入的 SQL 裡特別簡單。我們不用 把數據貼到語句中,這樣必然會有各種復雜事情需要處理,比如正確給數值 加引號等等,我們只需要在 SQL 語句裡寫上 C 變量的名字,前綴一個冒號即可。 比如:
EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);
這個語句引用了兩個 C 變量,一個叫 v1,另一個叫 v2,並且也使用一個普通的 SQL 字串文本,這樣表明 你並不局限于只使用某一種數據。
這種在 SQL 語句裡插入 C 變量的方式在 SQL 語句裡任何需要表達式的地方 都可以用。在 SQL 語句裡,我們把引用的 C 變量叫做 宿主變量。
要從程序中向數據庫傳遞數據,比如,查詢中的參數,或者從數據庫裡 向程序傳回的數據,想包含這類數據的 C 變量必須在一個特殊的標記段 裡面聲明,這樣嵌入的 SQL 預處理器就會明白要做什麼。
這個段以下面的代碼開頭
EXEC SQL BEGIN DECLARE SECTION;
以下面的代碼結束
EXEC SQL END DECLARE SECTION;
在這兩行之間,是普通的 C 變量聲明,比如
int x; char foo[16], bar[16];
在程序裡你可以有任意多個聲明段。
這些聲明也同時以普通 C 變量的形式回顯到輸出文件中, 因此,我們不必再次聲明他們。那些不準備在 SQL 命令裡使用的 變量可以像通常一樣在這些特殊的段外面聲明。
結構或者聯合的定義也必須在 DECLARE 段中列出。 否則,預處理器就無法處理這些類型,因為它不知道定義。
特殊的類型 varchar 對每個變量都轉化成一個叫 struct 的名字。像下面這樣的聲明:
varchar var[180];
轉化成
struct varchar_var { int len; char arr[180]; } var;這個結構適合于和 SQL 數據類型 varchar 的數據交互。
現在你應該能把你的程序生成的數據傳遞到 SQL 命令裡面去了。但是你如何 檢索一個查詢的結果呢?為了這個目的,嵌入的 SQL 提供了常用命令 SELECT 和 FETCH 的特殊變體。 這些命令有了特殊的 INTO 子句,聲明檢索出來的數值 存儲在哪個宿主變量裡。
下面是一些例子:
/* * 假設表是這個: * CREATE TABLE test1 (a int, b varchar(50)); */ EXEC SQL BEGIN DECLARE SECTION; int v1; VARCHAR v2; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT a, b INTO :v1, :v2 FROM test;
所以,INTO 子句出現在選擇列表和 FROM 子句之間。選擇列表和 INTO 後面的列表的元素(也叫目標列表)個數必須相同。
下面是使用 FETCH 命令的例子:
EXEC SQL BEGIN DECLARE SECTION;
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test;
...
do {
...
EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2;
...
} while (...);這裡的 INTO 子句出現在所有正常的子句後面。
這些方法只能一次檢索一行。如果你需要處理可能多于一行的結果集, 那麼你需要使用遊標,就想我們第二個例子演示的那樣。
上面的例子不能處理空值。實際上,如果從數據庫中抓到一條空值,那麼 上面的檢索例子會拋出一個錯誤。要能夠向數據庫中傳遞空值,或者從數據庫 中檢索空值,你需要給每個包含數據的宿主變量後面附加一個額外的宿主變量。 這第二個宿主變量叫指示器,裡面包含一個標志, 告訴我們數據是否為空,如果為空,那麼真正的宿主變量的數值就可以忽略。 下面是一個能正確檢索空值的例子:
EXEC SQL BEGIN DECLARE SECTION; VARCHAR val; int val_ind; EXEC SQL END DECLARE SECTION: ... EXEC SQL SELECT b INTO :val :val_ind FROM test1;
如果數值不是空,那麼指示器變量 val_ind 將是零, 如果值是空,那麼它將是負數。
指示器還有另外一個用途:如果它是正數,那麼它標識數值不是空, 但是在數值存儲到宿主變量裡的時候被截斷了。