| WHENEVER 類型 | 觸發條件 | 插入代碼模式 |
| SQLERROR | sqlca.sqlcode < 0 | if (sqlca.sqlcode < 0) { action; } |
| NOT FOUND | sqlca.sqlcode == 1403 (ORA-01403) | if (sqlca.sqlcode == 1403) { action; } |
| SQLWARNING | sqlca.sqlwarn[0] == 'W' | if (sqlca.sqlwarn[0] == 'W') { action; } |
實戰案例推演
案例 1:不同類型獨立生效
EXEC SQL WHENEVER SQLERROR DO sql_error("msg"); // 定義1
// ... 多條 SQL ...
EXEC SQL WHENEVER NOT FOUND DO break; // 定義2
// ... SELECT/FETCH ...
EXEC SQL WHENEVER NOT FOUND CONTINUE; // 定義3 覆蓋定義2
- 定義1:作用域從此處至文件末尾(無同類覆蓋)
- 定義2:作用域至定義3前
- 定義3:作用域至文件末尾
- 後續發生
SQLERROR 仍按定義1處理,不受 2/3 影響
案例 2:同類覆蓋鏈
EXEC SQL WHENEVER SQLERROR DO sql_error(); // A
EXEC SQL WHENEVER NOT FOUND GOTO exit_label; // B
EXEC SQL WHENEVER SQLERROR CONTINUE; // C 覆蓋 A
EXEC SQL SELECT ...; // 此處 SQLERROR→CONTINUE, NOT FOUND→GOTO
EXEC SQL WHENEVER SQLERROR STOP; // D 覆蓋 C
EXEC SQL FETCH ...; // 此處 SQLERROR→STOP, NOT FOUND→GOTO
案例 3:跨函數影響(關鍵陷阱)
// file.pc
void helper() {
EXEC SQL WHENEVER SQLERROR STOP; // 影響 main 中後續 SQL!
}
int main() {
EXEC SQL WHENEVER SQLERROR DO handle();
EXEC SQL CONNECT ...; // 這裡用 handle()
helper(); // 調用 helper,但 helper 內無 SQL
EXEC SQL SELECT ...; // 這裡用 STOP!因 helper 內的定義生效
}
教訓: WHENEVER 不遵循 C 語言作用域規則,勿在函數內定義 WHENEVER,應集中在文件開頭或模塊邊界管理。
生成代碼對比(簡化)
/* 原始 Pro*C */
EXEC SQL WHENEVER SQLERROR DO sql_error("msg");
EXEC SQL CONNECT :usr;
/* 預編譯後 C */
{ if (sqlca.sqlcode < 0) sql_error("msg"); } // CONNECT 後插入
EXEC SQL WHENEVER NOT FOUND GOTO exit;
EXEC SQL SELECT ...;
/* 生成 */
{ if (sqlca.sqlcode == 1403) goto exit;
if (sqlca.sqlcode < 0) sql_error("msg"); } // 兩類檢查並存
最佳實踐建議
- 統一錯誤策略:項目規範統一用
WHENEVER SQLERROR GOTO error_label 或 DO 回調,避免混用
- 集中定義:文件頂部定義全局策略,極少數局部場景用
CONTINUE 臨時屏蔽並緊接恢復
- 禁用函數內定義:防止跨函數污染
- 檢查生成代碼:編譯保留
.c 文件 (proc ... CODE=C),核實插入邏輯
- 配合 sqlca 手動檢查:關鍵操作顯式判斷
sqlca.sqlcode,不完全依賴 WHENEVER
總結
WHENEVER 是預編譯器層面的文件級宏替換指令,非運行時機制。理解其「類型隔離、同類覆蓋、文件局部」三大規則,配合查看生成的 C 代碼,即可精準控制 SQL 錯誤處理流程,避免「明明定義了 CONTINUE 卻跳轉到錯誤標籤」等離譜 Bug。
- 上一篇文章: Winsock 編程入門:Client 端核心 API 與多線程端口掃描器實戰
- 下一篇文章: Pro*C 編程實戰筆記:環境配置、數據類型映射、數組操作與預編譯選項全攻略
Copyright ©
程式碼之家 All Rights Reserved