| PostgreSQL 8.0.0 中文文件(轉譯自 PostgreSQL 中國 製作的簡體中文版本) | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 29. ecpg - 在 C 裡嵌入 SQL | Fast Forward | Next |
在 Section 29.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 將是零, 如果值是空,那麼它將是負數。
指示器還有另外一個用途:如果它是正數,那麼它標識數值不是空, 但是在數值儲存到宿主變量裡的時候被截斷了。