| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 30. ecpg - 在 C 裡嵌入 SQL | Fast Forward | Next |
本節描速你如何在嵌入的 SQL 程序裡處理例外以及警告。有好幾種非排它 的設施可用。
捕獲錯誤和警告的一個簡單的辦法是設置一個特定的動作, 當特定情況發生的時候執行這個動作。通常:
EXEC SQL WHENEVER condition action;
condition 可以是下列之一:
聲明的動作將在執行一個 SQL 語句發生錯誤的時候執行。
聲明的動作將在執行一個 SQL 語句發生警告的時候執行。
聲明的動作將在一條 SQL 語句檢索了零行或者影響零行的情況下被 執行。(這個條件不是一個錯誤,但是你可能喜歡單獨處理這個情況。)
action 可以是下列之一:
這個動作的意思是這個條件可以忽略。這是缺省。
跳轉到指定的標簽(使用一個 C 的goto 語句)。
向標準錯誤打印一條信息。這對簡單程序或者原型定義程序很有用。 消息的細節不能配置。
調用 exit(1),它將終止程序運行。
執行 C 語句 break。這個應該只在循環或者 switch 語句中使用。
用指定的參數調用指定的 C 函數。
SQL 標準只提供 CONTINUE 和 GOTO (也是 GO TO)動作。
下面是一個例子,你可能可以用在簡單的程序裡。它在發生警告的時候打印 一個簡單的信息,在發生錯誤的時候退出程序。
EXEC SQL WHENEVER SQLWARNING SQLPRINT; EXEC SQL WHENEVER SQLERROR STOP;
語句 EXEC SQL WHENEVER 是 SQL 預處理器的一個指示器, 而不是一個 C 語句。它設置的錯誤或者警告動作適用于下面出現的設置了句柄的 所有 SQL 語句,除非在第一個 EXEC SQL WHENEVER 和 導致條件觸發的 SQL 語句之間為同一個條件設置了另外一個動作,而不管 C 程序 內部的流程控制是怎樣的。所以,下面的兩個 C 程序節選都不會有它們期望的效果。
/*
* 錯誤
*/
int main(int argc, char *argv[])
{
...
if (verbose) {
EXEC SQL WHENEVER SQLWARNING SQLPRINT;
}
...
EXEC SQL SELECT ...;
...
}
/*
* 錯誤
*/
int main(int argc, char *argv[])
{
...
set_error_handler();
...
EXEC SQL SELECT ...;
...
}
static void set_error_handler(void)
{
EXEC SQL WHENEVER SQLERROR STOP;
}
如果需要更強大的錯誤處理機制,那麼嵌入的 SQL 接口提供了一個叫 sqlca 的全局變量,它是一個有著下面定義的結構:
struct
{
char sqlcaid[8];
long sqlabc;
long sqlcode;
struct
{
int sqlerrml;
char sqlerrmc[70];
} sqlerrm;
char sqlerrp[8];
long sqlerrd[6];
char sqlwarn[8];
char sqlstate[5];
} sqlca;(在一個多線程的程序裡,每個線程自動獲得自己的 sqlca 的拷貝。這個方式類似于處理標準 C 全局變量 errno。)
sqlca 包含警告和錯誤。如果在一個語句的執行 中出現多個警告或者錯誤,那麼 sqlca 將只包含 最後一個的信息。
如果在最後的 SQL 語句執行過程中沒有發生錯誤, 那麼 sqlca.sqlcode 將是 0 並且 sqlca.sqlstate 將是"00000"。如果發生一個警告或者錯誤, 那麼 sqlca.sqlcode 將是負數並且 sqlca.sqlstate 將不是 "00000"。一個正數的 sqlca.sqlcode 標識一種無害的條件,比如最後的查詢返回零行。sqlcode 和 sqlstate 是兩個不同的錯誤模式;下面詳細介紹。
如果最後一條 SQL 語句成功,如果適合該具體命令,那麼 sqlca.sqlerrd[1] 包含處理過的行的 OID,而 sqlca.sqlerrd[2] 包含 處理或返回的行數。
在發生錯誤或者警告的情況下,sqlca.sqlerrm.sqlerrmc 將包含一個描述該錯誤的字串。字段 sqlca.sqlerrm.sqlerrml 包含存儲在 sqlca.sqlerrm.sqlerrmc 裡的錯誤信息 的長度(strlen() 的結果,對 C 程序員來說並非 真正關心的)。
在發出警告的情況下,sqlca.sqlwarn[2] 被設置 為 W。(在所有其它的情況下,它都被設置為與 W 不同的東西。)如果sqlca.sqlwarn[1] 設置為 W,那麼就是一個數值在存儲到宿主變量的時候被 截斷。如果任何其它元素設置成表示一個警告,那麼 sqlca.sqlwarn[0] 被設置為 W。
字段 sqlcaid,sqlcabc, sqlerrp 和剩下的 sqlerrd 以及 sqlwarn 元素目前沒有包含有用的信息。
結構 sqlca 沒有在 SQL 標準裡定義,但是在好幾個 其它 SQL 數據庫系統裡定義了。定義的核心都類似,但是如果你想寫可以 移植的應用,那麼你應該仔細研究不同的實現。
字段 sqlca.sqlstate 和 sqlca.sqlcode 是提供錯誤代碼的兩種不同的模式。兩種都在 SQL 裡聲明了,但是 SQLCODE 在 1992 年的標準版本裡標注為廢棄的,並且 在 1999 年版本裡被刪除了。因此,對于新應用,我們強烈建議使用 SQLSTATE。
SQLSTATE 是一個五字符的數組。五個字符包含數值 或者大寫字母,代表各種錯誤或者警告條件的代碼。SQLSTATE 有個層次化的模式:頭兩個字符標識條件的通常表示錯誤條件的類別, 後三個字符表示在該通用類中的子類。成功的狀態是由 00000 標識的。SQLSTATE 代碼在大多數地方都是定義在 SQL 標準裡的。PostgreSQL 服務器本機支持 SQLSTATE 錯誤代碼;因此在應用裡使用這個錯誤代碼模式 可以實現非常高的一致性。更多信息請參閱 Appendix A。
SQLCODE 是廢棄的錯誤代碼模式,是一個簡單的整數。 0 標識成功,正數標識帶著額外信息的成功,負數表示一個錯誤。SQL 標準 只定義了正數值 +100,這個表示最後的命令返回零行或者影響了零行,並且 沒有特定的負數值。因此,這個模式只能實現很有限的一致性並且並沒有 一個層次化的代碼機制。歷史上,PostgreSQL 的 嵌入的 SQL 處理器為自己使用賦予了一些 SQLCODE 的數值,這些都在下面列出,包括他們的數值和符號名。記住這些是不能移植到 其它 SQL 實現中去的。為了簡化應用向 SQLSTATE 模式 的移植,我們還列出了 SQLSTATE。不過,這兩個模式 之間沒有一對一或者一對多的映射(包括多對多),所以在任何情況下你都應該參考在 Appendix A 裡列出的全局SQLSTATE。
這些是已經賦值的 SQLCODE 數值:
表明你的虛擬內存已經耗盡(SQLSTATE YE001)
表明預處理器生成了一些庫不知道的東西。可能你運行的預處理器版本 和庫版本不同。(SQLSTATE YE002)
這意味著你的命令聲明了比命令預期要多的宿主變量(SQLSTATE 07001 或者 07002)
這意味著你的命令聲明了比命令預期要少的宿主變量(SQLSTATE 07001 或者 07002)
這意味著查詢返回了多行,但是語句只準備存儲一行結果(比如, 因為聲明的變量不是數組)。(SQLSTATE 21000)
宿主變量是 int 類型,而數據庫裡的數據是其它類型, 並且包含無法解釋成 int 類型的數值。庫使用 strtol() 做這種轉換。(SQLSTATE 42804)
宿主變量是 unsigned int 而數據庫裡的數據是其它類型, 並且包含無法解釋成 unsigned int 類型的數值。 庫使用 strtoul() 做這種轉換。(SQLSTATE 42804)
宿主變量是 float 而數據庫裡的數據是其它類型, 並且包含無法解釋成 float 類型的數值。 庫使用 strtod() 做這種轉換。(SQLSTATE 42804)
這意味著宿主變量是類型為 bool 的而數據庫中 的數據既不是't' 也不是 'f'。(SQLSTATE 42804)
發送給 PostgreSQL 服務器的語句是空的。 (這個通常不能在嵌入 SQL 程序裡出現,因此它可能是一個內部錯誤。) (SQLSTATE YE002)
返回了一個空值,但是沒有提供空值指示器變量。(SQLSTATE 22002)
在一個需要數組的地方使用了一個普通變量。(SQLSTATE 42804)
在一個需要數組的地方數據庫返回了一個普通變量。 (SQLSTATE 42804)
程序視圖訪問一個不存在的連接。(SQLSTATE 08003)
程序視圖訪問一個存在但未打開的連接(這是一個內部錯誤。)(SQLSTATE YE002)
你正在嘗試使用的語句還沒準備好。(SQLSTATE 26000)
聲明的描述符沒有找到。你在試圖使用的語句沒有準備好(SQLSTATE 33000)
聲明的描述符索引超出範圍。(SQLSTATE 07009)
請求了一個非法的描述符項。(這是一個內部錯誤。)(SQLSTATE YE002)
在一個動態語句的執行的過程中,數據庫返回了一個數字只,而宿主變量 不是數值型(SQLSTATE 07006)。
在執行一個動態語句的過程中,數據庫返回了一個非數字數值,但是宿主 變量是數值型。(SQLSTATE 07006)
一些 PostgreSQL 服務器導致的錯誤。 消息包含來自 PostgreSQL 服務器的錯誤消息。
PostgreSQL 告訴我們不能啟動,提交, 或者回滾這個事務。(SQLSTATE 08007)
與數據庫的連接企圖沒有成功(SQLSTATE 08001)。
這是個無害的條件,表示最後一條命令檢索或者處理了零行,或者你在 遊標的結尾。(SQLSTATE 02000)