COMMIT是否可以在PostgreSQL 9.5的匿名plgpsql函数中工作?


8

我正在将大量大文件导入到许多表中,这些表将使用匿名plpgsql代码块内的循环进行分区$do$

$do$
BEGIN
    FOR yyyy in 2012..2016 THEN 
        EXECUTE $$COPY table$$||yyyy||$$ FROM 'E:\data\file$$||yyyy||$$.csv DELIMITER ',' CSV;$$;
    END LOOP;
END;
$do$ LANGUAGE plpgsql

整个过程大约需要15个小时,我希望如果某个时刻出现导入错误,所有导入都不会回滚。

IIRC COMMIT在存储的函数中不起作用,因为整个函数被视为单个事务。

文档中$do$

将代码块视为没有参数的函数的主体,并返回void。它被解析并执行一次。

我假设这意味着整个$do$事务是一个事务,因此在该块内的提交将不起作用。我对么?


1
尝试BEGINCOMMIT在功能体内。您将获得一个例外,因为这是不允许的(不可能)。
Erwin Brandstetter,2016年

Answers:


9

没有,

您无法控制plpgsql函数(或匿名块)中的事务。

您在块外创建事务的唯一选择,例如:

BEGIN;

DO $$
  -- function stuff

  -- but if you use a exception, you will force a rollback
  RAISE EXCEPTION 'message';
$$ LANGUAGE 'plpgsql';

COMMIT; -- OR ROLLBACK

顺便说一句,DO BLOCKS与返回的功能具有相同的作用void

请在文档中查看更多信息:


我们是否仍然如此?我有一个需要循环数百次的函数。第一个循环在第7个循环接近一个小时后需要2秒,而在第10个循环之后我什么也没看到。
丹尼斯·鲍祖斯

1

在“ DO”块(或函数)中提交的唯一解决方案(对于Postgresql版本小于11)是使用dblink连接到同一服务器并在其中执行查询。只要记住变量和临时对象的可见性即可。

有关dblink的更多信息, 当“ DO-block”未在其他事务中运行时,可从“ DO”块内部以Postgresql-11开头进行事务控制。


postgresql.org/docs/11/sql-do.html指出“仅当DO在其自己的事务中执行时,才允许事务控制语句。” 对于9.5,这当然是不正确的。OTOH与dblink您将打开另一个交易,因此COMMIT,如果我没有记错的话,在那里的呼叫不会影响呼叫交易。
dezso

我的错。Postgresql-11中引入了“ DO”中的事务控制。我只是检查10.4仍然无法正常工作。
Dzhureedzh

@dezso感谢您向我指出这一点,即使在PG11服务器上,我也在使用dblink方法。
Dzhureedzh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.