web-dev-qa-db-ja.com

COMMITはPostgreSQL 9.5の匿名のplgpsql関数内で機能しますか?

匿名の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を返します。解析と実行は1回です。

これは、$do$全体が1つのトランザクションであるため、ブロック内でのコミットが機能しないことを想定しています。私は正しいですか?

8
raphael

番号、

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を返す関数と同じ効果があります。

詳しくはドキュメントをご覧ください:

9

「DO」ブロック(または関数)内でコミットする唯一の解決策(Postgresqlバージョンが11未満の場合)は、同じサーバーへのdblink接続を使用してそこでクエリを実行することです。変数と一時オブジェクトの可視性を覚えておいてください。

dblinkの詳細情報 Postgresql-11以降、「DOブロック」が他のトランザクション内で実行されていない場合でも、「DO」ブロック内からのトランザクション制御を使用できます。

1
Dzhureedzh