4.6. 错误处理

嵌入的 SQL 接口提供了一种简单的,但是也很全面的方法来处理 程序里的例外条件。的一种方法会在一定的条件发生的时候自动打印 一些信息。比如:

EXEC SQL WHENEVER sqlerror sqlprint;

或者

EXEC SQL WHENEVER not found sqlprint;

这个错误句柄在整个程序里面都有效。

注意: 这可不是EXEC SQL WHENEVER语句 用法的穷尽的例子。有关用法的更多例子可以在 SQL 手册里找到(比如, Groff 和 Weinberg 写的The LAN TIMES Guide to SQL)。

如果需要更强大的错误处理,那么嵌入的 SQL 接口提供了 一个 struct 和一个变量,名字叫 sqlca, 如下所述:

struct sqlca
{
    char sqlcaid[8];
    long sqlabc;
    long sqlcode;
    struct
    {
        int sqlerrml;
        char sqlerrmc[70];
    } sqlerrm;
    char sqlerrp[8];

    long sqlerrd[6];
    /* 0: 空                                        */
    /* 1: 如果适用,则时被处理行的 OID              */
    /* 2: 在 INSERT, UPDATE,或者 DELETE 语句中     */
    /*    处理的行数                                */
    /* 3: 空                                         */
    /* 4: 空                                         */
    /* 5: 空                                         */

    char sqlwarn[8];
    /* 0: 如果至少还有一个是 'W',则设置为 'W'       */
    /* 1: 如果至少有一个字符串数值在存储到           */
    /*    某个宿主变量时被截断了,则设置为'W'        */
    /* 2: 空                                         */
    /* 3: 空                                         */
    /* 4: 空                                         */
    /* 5: 空                                         */
    /* 6: 空                                         */
    /* 7: 空                                         */

    char sqlext[8];
} sqlca;

(许多空的数域可能在将来的版本中使用。)

如果没有发生错误,那么最后的 SQL 语句, sqlca.sqlcode 将会是 0(ECPG_NO_ERROR)。 如果 sqlca.sqlcode 小于零,那么这是一个严重的 错误,比如像数据库定义和查询不匹配等等。如果它大于零, 那么它是一个普通的错误,比如像表不包含要求的行等等。

sqlca.sqlerrm.sqlerrmc 将包含一个描述错误 的字串。这个字串以(发生错误的)源代码文件中的行数结束。

下面是可能发生的错误:

-12: Out of memory in line %d.

通常不应该发生。这表明你的内存耗尽了。

-200 (ECPG_UNSUPPORTED): Unsupported type %s on line %d.

通常不应该发生。这表明预处理器生成了一些库不认识的东西。 可能你运行的预处理器和库的版本不兼容。

-201 (ECPG_TOO_MANY_ARGUMENTS): Too many arguments line %d.

这意味着服务器 返回了比我们的匹配变量更多的参数. 可能你漏了几个 INTO :var1,:var2-列表里的宿主变量.

-202 (ECPG_TOO_FEW_ARGUMENTS): Too few arguments line %d.

这意味着服务器 返回了比我们的对应宿主变量要少的参数. 可能你多输入了几个 INTO :var1,:var2-列表里的宿主变量.

-203 (ECPG_TOO_MANY_MATCHES): Too many matches line %d.

这意味着查询返回了多个行,但你声明的变量不是数组. SELECT命令不是唯一的.

-204 (ECPG_INT_FORMAT): Not correctly formatted int type: %s line %d.

这意味着宿主变量是一个 int 类型而 PostgreSQL 数据库里的字段是另一种类型, 包含着一个不能转换成一个 int 类型的数值.库(函数)使用 strtol() 做此类转换.

-205 (ECPG_UINT_FORMAT): Not correctly formatted unsigned type: %s line %d.

这意味着宿主变量是一个 unsigned int (无符号整数)类型而 PostgreSQL 数据库里的字段是另外一种类型 并且包含一个不能转换成 unsigned int的数值.库(函数)使用 strtoul() 做这类转换.

-206 (ECPG_FLOAT_FORMAT): Not correctly formatted floating-point type: %s line %d.

这意味着宿主变量是一个 float (浮点)类型而 PostgreSQL 数据库里的字段是另外一种类型并且 包含一个不能转换成 float的数值.库(函数)使用 strtod() 做这类转换.

-207 (ECPG_CONVERT_BOOL): Unable to convert %s to bool on line %d.

这意味着宿主变量是一个 bool (布尔)类型,而 PostgreSQL 数据库里的字段值既不是't'也不是'f'

-208 (ECPG_EMPTY): Empty query line %d.

查询实际上是空的。 (通常在嵌入的 SQL 程序里不可能发生,因此它可能指向一个内部错误。)

-209 (ECPG_MISSING_INDICATOR): NULL value without indicator in line %d.

收到了一个 NULL 返回但是没有提供 NULL 指示符变量。

-210 (ECPG_NO_ARRAY): Variable is not an array in line %d.

是因为在一个需要数组的地方使用了一个普通变量.

-211 (ECPG_DATA_NOT_ARRAY): Data read from backend is not an array in line %d.

数据库在一个需要数组数值的地方返回了一个普通变量.

-220 (ECPG_NO_CONN): No such connection %s in line %d.

程序试图访问一个不存在的联接。

-221 (ECPG_NOT_CONN): Not connected in line %d.

程序试图访问一个存在的,但是没有打开的联接。

-230 (ECPG_INVALID_STMT): Invalid statement name %s in line %d.

你试图使用的语句还没准备好。

-240 (ECPG_UNKNOWN_DESCRIPTOR): Descriptor %s not found in line %d.

没有找到你声明的描述符.你试图使用的语句没有准备好.

-241 (ECPG_INVALID_DESCRIPTOR_INDEX): Descriptor index out of range in line %d.

声明的描述符索引超出了范围.

-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM): Unknown descriptor item %s in line %d.

没有找到你声明的描述符.你试图使用的语句没有准备好.

-243 (ECPG_VAR_NOT_NUMERIC): Variable is not a numeric type in line %d.

数据库返回了一个数字数值,而该变量不是数字数值.

-244 (ECPG_VAR_NOT_CHAR): Variable is not a character type in line %d.

数据库返回了一个非数字数值,但该变量是数字类型.

-400 (ECPG_PGSQL): '%s' in line %d.

某种 PostgreSQL 错误。该消息包含来自 PostgreSQL 后端的信息。

-401 (ECPG_TRANS): Error in transaction processing line %d.

PostgreSQL 给我们的信号,告诉我们无法开始,提交或者回卷该事务。

-402 (ECPG_CONNECT): Could not connect to database %s in line %d.

与数据库的联接无法工作。

100 (ECPG_NOT_FOUND): Data not found line %d.

这是一个"正常的"错误, 告诉你你正在查询的东西找不到或者我们已经到了游标的结尾。