更新时间:2026-10-21 GMT+08:00
用WHENEVER指令控制流程
EXEC SQL WHENEVER是ecpg预编译器提供的声明式指令,用于指定当嵌入式SQL语句触发异常、告警或特定结果时的自动化处理动作。预编译器会在源代码文本的后续SQL语句之后,自动插入相应的判断与控制流代码。
语法格式如下:
EXEC SQL WHENEVER condition action;
触发条件(condition)取值范围:
- SQLERROR:当在SQL语句执行期间发生错误时触发,调用指定操作。
- SQLWARNING:当在SQL语句执行期间发生告警时触发,调用指定操作。
- NOT FOUND:当SQL查询检索或受影响的数据行数为零时触发,调用指定操作。
处理动作(action)取值范围:
- CONTINUE:忽略错误或告警条件,继续向下执行,这是系统的默认缺省动作,常用于重置或取消之前设置的WHENEVER规则。
- GOTO label/GO TO label:跳转到指定label(使用C语言goto语句)。
- SQLPRINT:将错误或告警消息直接打印输出至标准错误输出(stderr)。
- STOP:直接调用exit(1)终止整个应用程序的运行。
- DO BREAK:执行C语句break,只能在循环(while、for)或者switch语句中使用。
基础示例如下:
/* 当出现一个告警时打印一个消息 */ EXEC SQL WHENEVER SQLWARNING SQLPRINT; /* 发生一个错误时中止程序。 */ EXEC SQL WHENEVER SQLERROR STOP;
- EXEC SQL WHENEVER 是 SQL 预处理器指令,而非C语言语句。它用于设置错误或警告的处理动作,该设置对后续所有嵌入式SQL语句生效,除非在第一个EXEC SQL WHENEVER语句与触发错误或警告的SQL语句之间,针对同一情况设置了不同的处理动作。因此下面的两个C语言程序都不会得到预期的效果:
/* 错误一:试图在C语言if分支中动态生效 */ void func() { ... if (verbose) { /* 预编译器在编译期解析此行,无论运行时verbose是否为真,该设置均对下方SQL生效 */ EXEC SQL WHENEVER SQLWARNING SQLPRINT; } ... EXEC SQL SELECT ...; ... }/* 错误二:试图通过函数封装在运行期生效 */ void func() { ... set_error_handler(); ... EXEC SQL SELECT ...; ... } static void set_error_handler(void) { /* WHENEVER仅对其在源码中物理位置下方的SQL生效,无法影响func()中的SQL */ EXEC SQL WHENEVER SQLERROR STOP; } - DO BREAK只能用于while/for/switch场景中自动响应NOT FOUND条件以跳出循环,在循环体结束之后,如果后续SQL操作不需要继续保持“未查到数据就跳出循环”的逻辑,必须显式使用EXEC SQL WHENEVER condition CONTINUE;来重置该条件,避免影响循环体外部的常规SQL语句。
父主题: 错误处理