4

根据文档(https://www.postgresql.org/docs/current/app-psql.html),即使设置为关闭,PSQL 也会在任何尚未在事务块中的命令之前AUTOCOMMIT发出隐式并且是BEGIN本身不是一个BEGIN或其他事务控制命令,也不是一个不能在事务块内执行的命令,例如VACUUM. (不幸CALL的是,没有以与 相同的方式对待VACCUM)。而且,根据肖恩·托马斯(https://blog.2ndquadrant.com/pg-phriday-stored-procedures-postgres-11/),无效事务终止错误发生是因为不可能从过程中关闭当前事务(在本例中是由 PSQL 启动的事务)。我已经尝试了所有与事务控制相关的 PSQL 设置,但是所有这些设置都发生了无效的事务终止错误;即使 PSQL 处理的命令文件只包含CALL语句。

这是我正在调用的程序:

create or replace procedure producto$cargar_imagenes(_super$ bigint, _archivo$ character varying) as $$
declare
    _msg character varying;
    _log rastro_proceso%ROWTYPE;
begin
    perform rastro_proceso_temporal$insert(_super$);
    perform producto$cargar_imagenes$biz(_super$, _archivo$);
    if (_super$ is not null and _super$ > 0) then
        perform producto$cargar_imagenes$log(_super$, _archivo$);
    else
        perform tarea_usuario$private$update(6519204281880642486, null);
    end if;
    commit;
end;
$$ language plpgsql set search_path = public;

它在commit声明中失败;如果我将其注释掉,它会起作用。

4

2 回答 2

3

删除SET子句。根据文档:

如果将 SET 子句附加到过程,则该过程不能执行事务控制语句(例如,COMMIT 和 ROLLBACK,具体取决于语言)。

于 2018-11-08T22:46:43.337 回答
1

如果在过程定义中包含“SECURITY DEFINER”子句,那么在 pg11(在 11.6 版中测试)中,您似乎会遇到同样的问题。所以我猜 SECURITY DEFINER 有资格作为“SET”子句。

当我删除 SECURITY DEFINER 时,我可以在过程定义中包含一个 COMMIT 语句,而不会在 COMMIT 语句上获得 ERROR:invalid transaction termination。

不幸的是,这是一个运行时错误,而不是编译错误。

于 2020-01-08T17:11:57.683 回答