生成带有上下文的异常


13

PostgreSQL引发异常时,将出现“ CONTEXT”行,例如:

    ERROR:  INSERT has more target COLUMNS than expressions
    LINE 3: ...
                                                         ^
    QUERY:  INSERT INTO ...
    CONTEXT:  PL/pgSQL FUNCTION "XXXXX" line 4 at SQL statement

但是当我抛出异常时,此行不存在。我没有找到如何添加它。

    RAISE EXCEPTION 'blablabla' USING HINT = 'blablablabla';

是否可以将此行添加到我的例外中?

Answers:


13

我找不到直接输出CONTEXT带有用户定义异常的行的方法。尚未在PostgreSQL 9.1中实现此选项。在此处阅读手册
但是,我发现了...

解决方法

...应该表现完美。您可以通过调用另一个引发错误的函数来使plpgsql表现出所需的行为。这适用于PostgreSQL 9.0或更高版本
对于8.4版,您必须进行一些小的调整:无法分配参数。

使用用户定义的消息和CONTEXT以下命令引发错误(警告,通知等)的功能:

CREATE OR REPLACE FUNCTION f_raise(_lvl text = 'EXCEPTION'
                                 , _msg text = 'Default error msg.')
  RETURNS void AS
$func$
BEGIN
   CASE upper(_lvl)
      WHEN 'EXCEPTION' THEN RAISE EXCEPTION '%', _msg;
      WHEN 'WARNING'   THEN RAISE WARNING   '%', _msg;
      WHEN 'NOTICE'    THEN RAISE NOTICE    '%', _msg;
      WHEN 'DEBUG'     THEN RAISE DEBUG     '%', _msg;
      WHEN 'LOG'       THEN RAISE LOG       '%', _msg;
      WHEN 'INFO'      THEN RAISE INFO      '%', _msg;
      ELSE RAISE EXCEPTION 'f_raise(): unexpected raise-level: "%"', _lvl;
   END CASE;
END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_raise(text, text) IS 'Raise error or given level with msg and context.
Call from inside another function instead of raising an error directly
  to get plpgsql to add CONTEXT (with line number) to error message.
$1 .. error level: EXCEPTION | WARNING | NOTICE | DEBUG | LOG | INFO
$2 .. error message';

使用该函数引发如下错误:

CREATE OR REPLACE FUNCTION test_err(text)
  RETURNS void AS
$func$
BEGIN
   -- do stuff    

   IF TRUE THEN  -- some condition here?
      -- instead of raising error like this:
      -- RAISE EXCEPTION 'unexpected parameter: "%"', $1;
      PERFORM f_raise('EXCEPTION', 'My message "' || $1 || '"');
   END IF;
END
$func$  LANGUAGE plpgsql;

呼叫:

SELECT test_err('wrong parameter');

默认值和命名参数

我改进了语法,并在函数定义中添加了默认值。如果调用时不带参数(或仅带参数),则默认值将用于缺少值。与命名参数结合使用,您几乎可以做任何事情。例子:

SELECT f_raise();
SELECT f_raise('WARNING');
SELECT f_raise(_msg := 'boohoo');
SELECT f_raise(_lvl := 'WARNING');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.