postgresql - PL/pgSQL 函数会自行自动提交吗?
问题描述
我在 PostgreSQL 11 上有一个 PL/pgSQL 函数,如下所示:
create or replace function public.process_single_usage(usage_p "UsagePs")
returns text
language plpgsql
as $function$
declare
return_msg text;
-- Variables used for business logic
begin
-- Business logic and error handling, return_msg variable is assigned to an error message on failure
-- or to an empty string on success.
-- A bunch of insert statements if no error arises.
return return_msg;
end
$function$;
如果任何一行出现错误消息,我是否可以使用第二个函数在表的每一行上运行第一个函数并回滚每个插入,或者我是否需要使用单个函数来控制事务?
解决方案
我可以使用第二个函数在表的每一行上运行第一个函数,如果任何一行结果出现错误消息,则回滚每个插入
AFUNCTION
始终在单个事务中运行。但我不认为这会妨碍您尝试做的事情。带有子句的块EXCEPTION
可以捕获异常并回滚子事务。根据“每个插入”的确切含义,这可能对您有用。
如果“每一行”是指整个操作中的每一行(子函数的多次调用),那么您不需要做任何额外的事情。如果发生异常,默认行为是回滚所有内容。
如果“每一行”是指受子函数一次调用影响的每一行,那么请考虑关于Trapping Errors的手册:
当一个
EXCEPTION
子句捕捉到错误时,PL/pgSQL 函数的局部变量保持与错误发生时一样,但对块内持久数据库状态的所有更改都将回滚。
大胆强调我的。有关的:
要COMMIT
在过程中的任何时候实际工作,您需要一个PROCEDURE
, Postgres 11 引入。从相同版本开始,事务控制语句也允许在使用DO
command执行的匿名代码块中。
基本上:
DO
$do$
DECLARE
_rec "UsagePs";
BEGIN
FOR _rec IN
SELECT * FROM "UsagePs" u WHERE u.foo = 'bar' ORDER BY u.id
LOOP
BEGIN
PERFORM public.process_single_usage(_rec);
-- COMMIT; -- ? -- requires Postgres 11
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'This error happened: %!', SQLERRM;
END;
END LOOP;
END
$do$;
我认为您甚至不需要或不想COMMIT
进入循环。您只想回滚子事务 - 或所有内容。
请注意使用SQLERRM
将任何错误消息从子函数传播出去,降级为WARNING
. 手册:
特殊变量
SQLERRM
包含与异常相关的错误消息。
有关的:
推荐阅读
- django - 如何在视图前实现令牌认证?
- c++ - 如何避免使用 node-gyp 生成的节点模块的单例行为?
- visual-studio-code - VSCode 编辑器没有填满所有可用空间
- haskell - 测试 IsString s => s -> Bool 函数的惰性
- javascript - Javascript 随机图像,点击按钮上有文字
- php - 如何在电子邮件 TO 标头中设置 PHP 变量?
- git - Git:在本地分支中进行编辑,以推回远程仓库
- regex - 查找并部分替换 Notepad++ 正则表达式
- azure-functions - 持久功能 Blob 触发器
- javascript - 如果填充,更改输入字段颜色