我创建了一个在 Postgres DB 上运行的脚本,只要打开自动提交,它在 DBeaver 中运行时就可以完美运行,但是当打开自动提交的情况下在 pgAdmin 中运行相同的脚本时,它会失败。
我将脚本简化为以下示例,该示例在 DBeaver 中也适用,但在所描述的条件下在 pgAdmin 中失败:
DO $$
BEGIN
ROLLBACK;
RAISE INFO 'Autocommit is ON.';
END $$;
DO $$
BEGIN
ROLLBACK;
RAISE INFO 'Autocommit is still ON.';
END $$;
当 pgAdmin 失败时,会显示以下错误:
ERROR: invalid transaction termination
CONTEXT: PL/pgSQL function inline_code_block line 3 at ROLLBACK
SQL state: 2D000
这对我来说表明它并不是真正在自动提交模式下运行,但每次我尝试时该设置肯定会打开。更重要的是,在不更改任何设置或运行脚本的方式的情况下,如果我只有上述
DO
块之一,它可以在 DBeaver 和 pgAdmin 中工作。因此,出于某种原因,在 pgAdmin 中执行脚本只允许每个脚本使用单个 DO
块,同时在这些 DO
块中使用自动提交和事务控制?我似乎找不到任何关于这种情况的文档,尽管这是一个相当具体的问题。
我还尝试使用“执行 SQL 脚本”按钮和“执行 SQL 查询”按钮(在为后者选择整个脚本之后)在 DBeaver 中执行示例脚本,并且它在两种情况下都有效,所以它似乎是一些东西pgAdmin 特定的(或者至少不影响 DBeaver)。
不幸的是,我需要能够控制
DO
块内的事务,以能够循环批量处理数据,并且能够在不完成整个脚本的情况下在数据处理上取得进展,因此它可能会失败并继续后来,所以我没有看到在 COMMIT
块内执行 DO
的替代方法。
一定是当 pgAdmin 一次执行多个命令时,它将它们包装在一个显式事务中。这会导致您观察到的错误。
我找不到告诉 pgAdmin 不要这样做的方法,因此您可以使用不同的交互式客户端或将作业编写为单个
DO
语句:
DO $$
BEGIN
ROLLBACK;
RAISE INFO 'Autocommit is ON.';
ROLLBACK;
RAISE INFO 'Autocommit is still ON.';
END $$;