更新时间:2026-10-21 GMT+08:00
分享

sqlca

sqlca(SQL Communication Area,SQL通信区)是嵌入式SQL接口提供的全局结构体变量,用于保存当前数据库语句执行后的状态、告警与错误诊断信息。在多线程环境下,系统会自动为每个线程维护一份独立的sqlca副本以保证线程安全。若单条SQL语句在执行期间触发多个告警或错误,sqlca仅保留最后一条产生的异常信息。

sqlca数据结构如下:
struct 
{ 
    char sqlcaid[8];     /* 固定标识符字符串 "SQLCA " */ 
    long sqlabc;         /* sqlca结构体本身的内存字节大小 */ 
    long sqlcode;        /* 错误状态码:0表示成功,<0表示错误,100表示未查到数据(NOT FOUND) */ 
    struct 
    { 
        int sqlerrml;    /* 错误消息文本的实际长度 strlen() */ 
        char sqlerrmc[SQLERRMC_LEN]; /* 错误描述字符串(以\0结尾,超长会被截断) */ 
    } sqlerrm;
    char sqlerrp[8];     /* 系统保留字段 */ 
    long sqlerrd[6];     /* 状态诊断信息数组:sqlerrd[1]存储处理行的OID,sqlerrd[2]存储受影响/返回的数据行数 */ 
    char sqlwarn[8];     /* 告警标志位数组:产生告警时sqlwarn[0]与sqlwarn[2]会被置为'W' */ 
    char sqlstate[5];    /* 5字节标准SQLSTATE状态码(如"00000"表示成功) */ 
} sqlca;

核心字段功能与诊断规则:

  • sqlcode与sqlstate:执行成功时,sqlcode为0且sqlstate为"00000";执行失败时,sqlcode为负数,sqlstate会返回符合SQL标准的5字节字符代码(例如"42P01"表示表或视图不存在)。具体的代码映射关系请参见SQLSTATE与SQLCODE。
  • sqlerrm:包含sqlerrmc(错误消息文本)与sqlerrml(字符串实际长度)。由于sqlerrmc数组在内存中预分配的容量固定为SQLERRMC_LEN,需要注意的是,部分较长的错误消息可能会被截断。
  • sqlerrd:sqlerrd[1]在数据插入或更新成功时记录对应行对象的OID;sqlerrd[2]记录当前SQL语句实际匹配、提取或修改的数据行数(如UPDATE修改的行数或SELECT查出的行数)。
  • sqlwarn:当出现告警信息时,系统会将sqlwarn[2]元素设置为字符'W'。sqlcaid、sqlabc、sqlerrp及sqlwarn的其余数组元素由系统内部保留使用。

在实际开发中,通常将EXEC SQL WHENEVER自动拦截指令与sqlca数据结构结合使用,实现异常的集中打印与分析。

示例如下,需要提前创建testdb:
#include <stdio.h>
#include <stdlib.h>
#include <sqlca.h>

/*错误处理回调函数:从全局sqlca结构体中提取诊断明细*/
void print_sqlca(void) 
{ 
    fprintf(stderr, "==== sqlca 诊断信息 ====\n");  
    fprintf(stderr, "sqlcode  : %ld\n", sqlca.sqlcode); 
    fprintf(stderr, "sqlstate : %.5s\n", sqlca.sqlstate); 
    fprintf(stderr, "sqlerrm  : %s (len=%d)\n", sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrm.sqlerrml); 
    fprintf(stderr, "sqlerrd2 : %ld (affected rows)\n", sqlca.sqlerrd[2]); 
    fprintf(stderr, "========================\n"); 
}

int main(void)
{
    /* 声明当发生SQL错误时自动调用print_sqlca函数 */
    EXEC SQL WHENEVER SQLERROR CALL print_sqlca();

    EXEC SQL CONNECT TO testdb;

    /* 故意执行一条查询不存在表名的语句以触发错误 */
    EXEC SQL SELECT * FROM pg_databasep;

    EXEC SQL DISCONNECT ALL;
    return 0;
}
运行结果如下(此处是一个拼写表名错误):
==== sqlca 诊断信息 ====
sqlcode  : -400
sqlstate : 42P01
sqlerrm  : relation "pg_databasep" does not exist on line 38 (len=49)
sqlerrd2 : 0 (affected rows)
========================

相关文档