PostgreSQL:如何捕获函数中的异常?

PostgreSQL:如何捕获函数中的异常?,postgresql,function,exception,Postgresql,Function,Exception,我有一张桌子和3个功能 fntrans调用->fntrans2调用->fntrans3 在本例中,我删除了对fntrans3()的调用 在这通电话之后 SELECT public.fntrans2(); 表t2包含记录,很明显,回滚工作到函数内部的保存点 但是当我打电话的时候 选择public.fntrans() 该表不包含任何行,输出显示fntrans中异常的通知 为什么在第二种情况下,异常被抛出到第一个函数,但当我调用fntrans2时,它只在这个函数中被捕获 create table t

我有一张桌子和3个功能 fntrans调用->fntrans2调用->fntrans3

在本例中,我删除了对fntrans3()的调用

在这通电话之后

SELECT public.fntrans2();
表t2包含记录,很明显,回滚工作到函数内部的保存点

但是当我打电话的时候 选择public.fntrans()

该表不包含任何行,输出显示fntrans中异常的通知

为什么在第二种情况下,异常被抛出到第一个函数,但当我调用fntrans2时,它只在这个函数中被捕获

create table t2(ID SERIAL PRIMARY KEY, f1 INTeger);

CREATE OR REPLACE FUNCTION "public"."fntrans" (
)
RETURNS integer AS
$body$
declare d double precision;
BEGIN
raise notice 'fntrans';
  INSERT INTO t2 (f1) VALUES (1);
  INSERT INTO t2 (f1) VALUES (2);
  INSERT INTO t2 (f1) VALUES (3);
  select fntrans2();
  INSERT INTO t2 (f1) VALUES (4);
  RETURN 1;
EXCEPTION  
  WHEN OTHERS THEN 
  BEGIN 
    raise notice 'fntrans exception';
    RETURN 0;
  END;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;


CREATE OR REPLACE FUNCTION public.fntrans2 (
)
RETURNS integer AS
$body$
declare d double precision;
BEGIN
    raise notice 'fntrans2';
    INSERT INTO t2 (f1) VALUES (10);
    INSERT INTO t2 (f1) VALUES (22);
    INSERT INTO t2 (f1) VALUES (30);

    BEGIN
            raise exception 'Oooooppsss 2!';
            INSERT INTO t2 (f1) VALUES (40);
            RETURN 1;
    EXCEPTION   
    WHEN OTHERS THEN RETURN 0;
    END;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE;


CREATE OR REPLACE FUNCTION public.fntrans3 (
)
RETURNS integer AS
$body$
declare d double precision;
BEGIN
   raise notice 'fntrans3';

  INSERT INTO t2 (f1) VALUES (100);
  INSERT INTO t2 (f1) VALUES (200);
  INSERT INTO t2 (f1) VALUES (300);
  raise exception 'Oooooppsss 3!';
  INSERT INTO t2 (f1) VALUES (400);
  RETURN 1;
EXCEPTION  
  WHEN OTHERS THEN RETURN 0;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;

你的问题是线路

select fntrans2();
fntrans
中。如果PL/pgSQL中没有
INTO
子句,则不能使用
SELECT

如果没有
异常
块,您将得到以下消息:

CONTEXT:  SQL statement "select fntrans2()"
PL/pgSQL function fntrans() line 8 at SQL statement
ERROR:  query has no destination for result data
HINT:  If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT:  PL/pgSQL function fntrans() line 8 at SQL statement
这是不言自明的。
它还解释了为什么您看不到函数
fntrans2
的任何结果–它不会被调用

你可以把冒犯的话改成

PERFORM fntrans2();

是的,你是对的,这是两个不同的例外,thnx!