我有一张桌子和3个功能 fntrans-calls-> fntrans2-calls-> fntrans3
在这个例子中,我删除了fntrans3();
的调用此次通话后
SELECT public.fntrans2();
表t2包含记录,好的,很明显,回滚对函数内部的保存点起作用
但是当我打电话的时候 SELECT 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;
答案 0 :(得分:3)
你的问题就在这一行
select fntrans2();
fntrans
中的。如果PL / pgSQL中没有SELECT
子句,则不能使用INTO
。
如果没有EXCEPTION
阻止,您将收到以下消息:
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();