我有一个在它(postgresql v11)中提交的过程,想从函数调用他的过程。得到以下错误的过程已经提交,当提交被删除,它工作正常。是否有任何工作能够调用过程与事务控制语句从一个函数(我知道函数不支持事务,这就是为什么它失败,但想知道是否有任何替代方案?)
CREATE OR REPLACE FUNCTION public.f()
RETURNS text
LANGUAGE plpgsql
AS $function$
BEGIN
raise notice 'Starting Function!!!';
call public.p();
return 'success' ;
END;
$function$;
CREATE OR REPLACE PROCEDURE public.p() LANGUAGE plpgsql AS $$
DECLARE src_schema TEXT;
BEGIN
raise notice 'Starting Procedure!!!';
commit;
RETURN;
END;
$$;
-- if the procedure has commit then its failing
imaods=> select public.f();
NOTICE: Starting Function!!!
NOTICE: Starting Procedure!!!
ERROR: invalid transaction termination
CONTEXT: PL/pgSQL function p() line 5 at COMMIT
SQL statement "CALL public.p()"
PL/pgSQL function f() line 4 at CALL
-- if the commit is removed from the procedure then it works fine
imaods=> CREATE OR REPLACE PROCEDURE public.p() LANGUAGE plpgsql AS $$
imaods$> DECLARE src_schema TEXT;
imaods$> BEGIN
imaods$> raise notice 'Starting Procedure!!!';
imaods$> RETURN;
imaods$> END;
imaods$> $$;
CREATE PROCEDURE
imaods=>
imaods=> select public.f();
NOTICE: Starting Function!!!
NOTICE: Starting Procedure!!!
f
---------
success
(1 row)
文档解释:
事务控制只能在来自顶层的
CALL
或DO
调用或嵌套的CALL
或DO
调用中实现,而不需要任何其他干预命令。例如,如果调用堆栈是CALL proc1()
→CALL proc2()
→CALL proc3()
,那么第二个和第三个过程可以执行事务控制操作。但是如果调用栈是CALL proc1()
→SELECT func2()
→CALL proc3()
,那么最后一个过程不能做事务控制,因为中间有SELECT
。
原因是你不能在PostgreSQL函数中进行事务管理。