Un COMMIT fonctionne-t-il dans une fonction plgpsql anonyme dans PostgreSQL 9.5?

8

J'importe un grand nombre de fichiers volumineux dans un certain nombre de tables à partitionner à l'aide de boucles dans un bloc de code plpgsql anonyme $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

L'ensemble de ce processus devrait prendre environ 15 heures et j'espère que toutes les importations ne seront pas annulées s'il y a une erreur d'importation à un moment donné.

IIRC COMMITne fonctionne pas dans les fonctions stockées car la fonction entière est traitée comme une seule transaction.

À partir de la documentation de$do$

Le bloc de code est traité comme s'il s'agissait du corps d'une fonction sans paramètre, renvoyant void. Il est analysé et exécuté une seule fois.

Je suppose que cela signifie que l'intégralité $do$est une transaction, et donc les validations dans le bloc ne fonctionneront pas. Ai-je raison?

raphael
la source
1
Essayez BEGINou COMMITdans le corps de la fonction. Vous obtiendrez une exception, car ce n'est pas autorisé (pas possible).
Erwin Brandstetter

Réponses:

9

Non,

Vous ne pouvez pas contrôler une transaction à l'intérieur d'une plpgsqlfonction (ou d'un bloc anonyme).

La seule option que vous avez sa création d'une transaction en dehors du bloc, par exemple:

BEGIN;

DO $$
  -- function stuff

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

COMMIT; -- OR ROLLBACK

BTW, DO BLOCKSont le même effet qui fonctionne qui revient void.

S'il vous plaît, voir plus sur le doc:

Sebastian Webber
la source
Savons-nous si c'est toujours le cas? J'ai une fonction qui doit boucler plusieurs centaines de fois. La première boucle prend 2 secondes après la 7e soit près d'une heure et je n'ai rien vu après la 10e boucle.
Dennis Bauszus
1

La seule solution à valider dans des blocs (ou fonctions) "DO" (pour la version Postgresql inférieure à 11) est d'utiliser une connexion dblink au même serveur et d'y exécuter vos requêtes. Gardez simplement à l'esprit la visibilité des variables et des objets temporaires.

plus d'informations sur dblink À partir de Postgresql-11, le contrôle des transactions depuis l'intérieur du bloc "DO" est disponible pendant que "DO-block" ne s'exécute pas dans une autre transaction.

Dzhureedzh
la source
postgresql.org/docs/11/sql-do.html indique que les instructions de contrôle des transactions ne sont autorisées que si DO est exécuté dans sa propre transaction. Ce n'était bien sûr pas vrai avec 9.5. OTOH avec dblinkvous ouvrira une autre transaction, donc votre COMMITappel n'affectera pas la transaction appelante, si je ne me trompe pas.
dezso
Ma faute. Le contrôle des transactions au sein de "DO" a été introduit dans Postgresql-11. Je vérifie simplement que 10.4 ne fonctionne toujours pas.
Dzhureedzh
@dezso Merci de m'avoir indiqué cela, j'utilisais la méthode dblink même sur les serveurs PG11.
Dzhureedzh