40.8. 错误和消息

利用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,默认的是EXCEPTIONEXCEPTION会抛出一个错误(强制关闭当前事务), 而其他级别仅仅是产生不同优先级的消息。 无论是将特定优先级别的消息报告给客户端,还是写到服务器日志,亦或是二者都是, 都是由log_min_messagesclient_min_messages配置变量控制的。 参阅第 18 章获取更多细节。

如果真有的话,在level之后, 你可以写format, (这必须是一个简单的字符串文本,而不是表达式)。 格式字符串声明要报告的错误消息文本。 格式字符串后面可以跟着要插入到消息中的可选的参数表达式。 在格式字符串里,%被下一个可选参数的外部表现形式代替。 要表示%字符必须发出(%%)。

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

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

你可以通过在option = expression项后边写USING来附加额外信息到错误报告中。 每一个expression可以是任何字符串值表达式。 允许的option关键字是:

MESSAGE

设置错误消息文本。这个选项不能用于包含USING之前的格式字符串 的RAISE形式中。

DETAIL

提供一个错误详细消息。

HINT

提供提示消息。

ERRCODE

指定错误代码(SQLSTATE)用来报告,通过条件名, 如附录 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语法,其中主要参数是条件名字或者要报告的SQLSTATE,比如:

RAISE division_by_zero;
RAISE SQLSTATE '22012';

在这个语法中,USING可以来提供一个通用的错误消息,详情,或者提示。另一个较早的例子是:

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

另一个变形是 写RAISE USING或者RAISElevel USING, 然后将其他的所有东西都放在USING列中。

最后一个RAISE变形中没有任何参数。 这种形式只能在BEGIN块的EXCEPTION字句中使用。 它的作用是将正在处理的错误放到下一个封闭的块中。

注意: PostgreSQL 9.1之前, 没有参数的RAISE被解释为 包含有活跃异常处理程序的块中重新抛出错误。 因此,EXCEPTION子句嵌套在该处理器中无法抓取它,即使 RAISE在嵌套的EXCEPTION子句块中。 这被认为是令人惊讶并且不兼容Oracle的PL/SQL。

如果RAISE EXCEPTION中没有声明SQLSTATE的情形名称, 那么缺省使用RAISE_EXCEPTION (P0001)。 如果没有声明消息文本,那么缺省将情形名称或SQLSTATE作为消息文本。

注意: 当通过SQLSTATE编码声明一个错误代码时,你不能限制预定义错误代码, 但是可以选择任何由五个数字和/或者大写ASCII字母组成的错误代码, 而不是00000。建议避免抛出以三个零结尾的错误代码,因为 这些是类别码并且只能通过捕获整个类别来获取。