web-dev-qa-db-fra.com

Restauration de pg_dump en texte brut avec psql et --disable-triggers

J'ai dû effectuer des tests avec un court script pour mettre à jour certaines données "héritées" dans l'une de mes tables.

Aussi prudent que je sois, en utilisant un script non testé, j'ai décidé de sauvegarder la table appropriée avant de le faire. La façon la plus simple de le faire était:

pg_dump -a --file table.sql -t table database

Maintenant, j'ai fait ce que j'avais à faire, vérifié les résultats et les ai trouvés plutôt insatisfaisants. Je me suis dit: quelle chance j'ai d'avoir une sauvegarde de cette table.

J'avais déjà été averti lorsque j'ai sauvegardé la table que:

pg_dump: NOTICE: there are circular foreign-key constraints among these table(s):
pg_dump:   table
pg_dump: You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.
pg_dump: Consider using a full dump instead of a --data-only dump to avoid this problem.

Je n'y pensais pas beaucoup, mais maintenant nous avons un problème. En effet, la table en question a plusieurs déclencheurs attachés, mais je ne peux pas restaurer le table.sql avec option --disable-triggers de la commande pg_restore.

Si j'essaie de suivre la commande, j'obtiens un message d'erreur:

pg_restore -a -d database -t table -h localhost --disable-triggers table.sql

à savoir:

pg_restore: [archiver] input file appears to be a text format dump. Please use psql.

Existe-t-il un indicateur pour la commande psql- qui présente le même comportement que --disable-triggers?

J'ai déjà vérifié le psql "manpage" , recherchant le déclencheur et les mots-clés similaires mais je n'ai rien trouvé.

Ou est-ce la seule option que je dois supprimer les déclencheurs sur la table avant de restaurer les données?

Sidenote: J'utilise postgres v. 9.3 sur un système Ubuntu 14.10


Il a été suggéré de modifier le fichier sql généré, pour inclure la déclaration:

ALTER TABLE table DISABLE TRIGGER ALL

Quand j'ai maintenant exécuté: psql -d database -f table.sql J'ai reçu un message d'erreur sur la violation de la contrainte "Unique" de la clé primaire.

Pour résoudre ce problème, j'ai essayé d'envelopper la copie dans:

BEGIN TRANSACTION READ WRITE;
TRUNCATE TABLE table;

-- copy here

COMMIT;

Maintenant, le message d'erreur est:

psql:project_backup.sql:18: ERROR:  cannot truncate a table referenced in a foreign key constraint
DETAIL:  Table "another" references "table".
HINT:  Truncate table "another" at the same time, or use TRUNCATE ... CASCADE.
psql:project_backup.sql:20: ERROR:  current transaction is aborted, commands ignored until end of transaction block
psql:project_backup.sql:21: invalid command \N
psql:project_backup.sql:22: invalid command \N

Ce dernier avertissement se répète pour chaque \N (symbolisant la valeur nulle) dans le vidage.

8
Vogel612

@dezso avait le idée tout à fait juste :

Tout cela signifie que certaines données ont été mises à jour, non? Essayez de les mettre à jour en utilisant une table temporaire dans laquelle vous copiez les données d'origine

Il ne restait plus qu'à y arriver.

Voici donc ce que j'ai fait. J'ai retiré une feuille de son livre et édité manuellement le fichier de vidage pour utiliser une table nommée table_backup. Ensuite, j'ai créé ladite table en utilisant la définition fournie dans mon pgAdmin (mais cela peut aussi être fait manuellement).

J'ai omis les déclencheurs et les contraintes, ainsi que les clés étrangères, puis j'ai "mis à jour" la table d'origine avec les données de la table de sauvegarde comme suit:

BEGIN TRANSACTION;
ALTER TABLE table DISABLE TRIGGER ALL;

UPDATE table SET 
    (column1, column2, ...) = 
    (table_backup.column1, table_backup.colum2, ...)
FROM table_backup WHERE table.pk_column = table_backup.pk_column;

ALTER TABLE table ENABLE TRIGGER ALL;
-- I didn't but you can drop table_backup here
COMMIT;

Je suis donc enfin de retour avec mes données d'origine, prêt pour le prochain test;)

4
Vogel612

Ajoutez cette ligne au vidage de données .sql:

set session_replication_role = replica;

et psql ne devrait pas se plaindre de la restauration.

0
Ivan Kozik