PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

41.9. 错误与日志消息 #

41.9.1. 报告错误与日志输出
41.9.2. 断言检查

41.9.1. 报告错误与日志输出 #

使用 RAISE 语句报告消息并引发错误。

RAISE [ level ] 'format' [, expression [, ... ]] [ USING option { = | := } expression [, ... ] ];
RAISE [ level ] condition_name [ USING option { = | := } expression [, ... ] ];
RAISE [ level ] SQLSTATE 'sqlstate' [ USING option { = | := } expression [, ... ] ];
RAISE [ level ] USING option { = | := } expression [, ... ];
RAISE ;

level 选项指定错误的严重级别。 允许的级别有 DEBUG、LOG、 INFO、NOTICE、 WARNING 和 EXCEPTION, 默认为 EXCEPTION。 EXCEPTION 会引发一个错误 (这通常会中止当前事务);其他级别只生成不同优先级的消息。 特定优先级的消息是报告给客户端、写入服务器日志,还是两者皆有, 由 log_min_messages 和 client_min_messages 配置变量控制。 更多信息见 Chapter 19。

在第一种语法变体中,在 level(如果有)之后, 书写一个 format 字符串 (它必须是简单的字符串字面值,不能是表达式)。 格式字符串指定要报告的错误消息文本。 格式字符串后面可以跟可选的参数表达式,它们会被插入消息中。 在格式字符串内部,% 会被下一个可选参数值的 字符串表示所替换。写 %% 可以输出一个字面的 %。参数的数目必须与格式字符串中 % 占位符的数目一致, 否则在函数编译期间会引发错误。

在这个例子中,v_job_id 的值将替换字符串中的 %:

RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;

在第二种和第三种语法变体中, condition_name 和 sqlstate 分别指定一个错误条件名或一个五字符的 SQLSTATE 代码。 有效的错误条件名和预定义的 SQLSTATE 代码见 Appendix A。

下面是 condition_name 和 sqlstate 用法的示例:

RAISE division_by_zero;
RAISE WARNING SQLSTATE '22012';

在上述任何一种语法变体中, 你都可以通过书写 USING 以及形如 option = expression 的条目,为错误报告附加额外的信息。每个 expression 可以是任何以字符串为值的表达式。允许的 option 关键字有:

MESSAGE #

设置错误消息文本。该选项不能用于第一种语法变体, 因为消息已经给出。

DETAIL #

提供错误的详细信息消息。

HINT #

提供提示消息。

ERRCODE #

指定要报告的错误代码(SQLSTATE),既可以按条件名指定 (如 Appendix A 所示), 也可以直接指定五字符的 SQLSTATE 代码。该选项不能用于第二种或第三种 语法变体,因为错误代码已经给出。

COLUMN
CONSTRAINT
DATATYPE
TABLE
SCHEMA #

提供相关对象的名称。

这个例子将以给定的错误消息和提示中止事务:

RAISE EXCEPTION 'Nonexistent ID --> %', user_id
      USING HINT = 'Please check your user ID';

这两个例子展示了设置 SQLSTATE 的等价方式:

RAISE 'Duplicate user ID: %', user_id USING ERRCODE = 'unique_violation';
RAISE 'Duplicate user ID: %', user_id USING ERRCODE = '23505';

产生相同结果的另一种方式是:

RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id;

如第四种语法变体所示,也可以书写 RAISE USING 或 RAISE level USING, 并把其余内容都放进 USING 列表。

RAISE 的最后一个变体完全不带参数。 这种形式只能在 BEGIN 块的 EXCEPTION 子句内部使用; 它会把当前正在被处理的错误重新抛出。

Note

在 PostgreSQL 9.1 之前, 不带参数的 RAISE 被解释为重新抛出来自 包含活动异常处理程序的块的错误。因此,嵌套在该处理程序内部的 EXCEPTION 子句无法捕获它, 即使该 RAISE 位于嵌套 EXCEPTION 子句的块中。 这一行为被认为出人意料,而且与 Oracle 的 PL/SQL 不兼容。

如果 RAISE EXCEPTION 命令中既没有指定条件名 也没有指定 SQLSTATE,默认将使用 raise_exception(P0001)。 如果没有指定消息文本,默认将使用条件名或 SQLSTATE 作为消息文本。

Note

通过 SQLSTATE 代码指定错误代码时,你并不局限于预定义的错误代码, 而是可以选择任何由五位数字和/或大写 ASCII 字母组成、 且不同于 00000 的错误代码。 建议避免抛出以三个零结尾的错误代码, 因为它们是类别代码,只能通过捕获整个类别来捕获。

41.9.2. 断言检查 #

ASSERT 语句是一种便捷的简写形式, 用于在 PL/pgSQL 函数中 插入调试检查。

ASSERT condition [ , message ];

condition 是一个预期总是求值为真的布尔表达式;如果确实如此, ASSERT 语句不会做任何 further 的事情。 如果结果为假或为空,则会引发 ASSERT_FAILURE 异常。(如果在求值 condition 时发生错误, 则该错误作为普通错误报告。)

如果提供了可选的 message, 它是一个表达式,当 condition 失败时, 其结果(如果不为空)将取代默认的错误消息文本 “assertion failed”。 在断言成功的正常情况下, message 表达式 不会被求值。

断言检查可以通过配置参数 plpgsql.check_asserts 启用或禁用, 该参数接受一个布尔值;默认值为 on。 如果该参数为 off, 则 ASSERT 语句什么也不做。

注意,ASSERT 旨在检测程序缺陷, 而不是报告普通的错误情况。后者请使用前面描述的 RAISE 语句。