更新时间: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语句。

相关文档