J'écris un script Shell (qui deviendra un travail cronjob) qui:
1: vider ma base de données de production
2: importer le dump dans ma base de développement
Entre les étapes 1 et 2, je dois effacer la base de développement (supprimer toutes les tables?). Comment cela est-il mieux réalisé à partir d'un script Shell? Jusqu'ici, cela ressemble à ceci:
#!/bin/bash
time=`date '+%Y'-'%m'-'%d'`
# 1. export(dump) the current production database
pg_dump -U production_db_name > /backup/dir/backup-${time}.sql
# missing step: drop all tables from development database so it can be re-populated
# 2. load the backup into the development database
psql -U development_db_name < backup/dir/backup-${time}.sql
Je laisserais simplement tomber la base de données et ensuite la recréer. Sur un système UNIX ou Linux, cela devrait le faire:
$ dropdb development_db_name
$ createdb developmnent_db_name
C'est comme ça que je le fais, en fait.
Si vous n'avez pas réellement besoin d'une sauvegarde de la base de données vidée sur le disque dans un format de fichier de script .sql en texte brut, vous pouvez vous connecter pg_dump
et pg_restore
directement ensemble sur un tuyau.
Pour supprimer et recréer des tables, vous pouvez utiliser le --clean
option de ligne de commande pour pg_dump
pour émettre des commandes SQL permettant de supprimer (supprimer) les objets de la base de données avant leur création. (Cela ne supprimera pas toute la base de données, mais seulement chaque table/séquence/index/etc. avant de les recréer.)
Les deux ci-dessus ressemblent à ceci:
pg_dump -U username --clean | pg_restore -U username
Bien que la ligne suivante soit extraite d'un script batch Windows, la commande doit être assez similaire:
psql -U username -h localhost -d postgres -c "DROP DATABASE \"$DATABASE\";"
Cette commande est utilisée pour effacer toute la base de données, en la supprimant réellement. Le $DATABASE
_ (sous Windows devrait être %DATABASE%
) dans la commande est une variable d’environnement de style Windows qui correspond au nom de la base de données. Vous devrez le remplacer par votre development_db_name
.
Jeter:
pg_dump -Fc mydb > db.dump
Restaurer:
pg_restore --verbose --clean --no-acl --no-owner -h localhost -U myuser -d my_db db/latest.dump
J'ai utilisé:
pg_restore -c -d database_name filename.dump
Pour les cas où vous ne pouvez pas simplement DROP SCHEMA public CASCADE;
, DROP OWNED BY current_user;
Ou quelque chose du genre, voici un script SQL autonome que j'ai écrit et qui est sécurisé pour les transactions (c'est-à-dire que vous pouvez le placer entre BEGIN;
Et soit ROLLBACK;
Pour le tester ou COMMIT;
Pour accomplir l'acte) et nettoie "tous" les objets de la base de données… eh bien, tous ceux utilisés dans la base de données que notre application utilise ou Je pourrais raisonnablement ajouter:
CHECK
, UNIQUE
)VIEW
s (normal ou matérialisé)pg_proc.proisagg
probablement devrait être respecté bien)public
ou internes à la base de données) "nous" possèdent: le script est utile lorsqu'il est exécuté en tant que "non superutilisateur de base de données"; un super-utilisateur peut supprimer tous schemata (les plus importants sont toujours explicitement exclus)Ne sont pas omis (certains délibérés; d'autres uniquement parce que je n'avais aucun exemple dans notre base de données):
public
(par exemple pour les éléments fournis par leur extension)J'ai également une version qui supprime "tout sauf deux tables et ce qui leur appartient" au cas où quelqu'un serait intéressé; le diff est petit. Contactez moi si nécessaire.
Ceci est vraiment utile dans les cas où le cliché que vous souhaitez restaurer est d'une autre version du schéma de base de données (par exemple, avec Debian dbconfig-common
, Flyway ou Liquibase/DB-Manul) que la base de données dans laquelle vous souhaitez la restaurer.
-- Copyright © 2019
-- mirabilos <[email protected]>
--
-- Provided that these terms and disclaimer and all copyright notices
-- are retained or reproduced in an accompanying document, permission
-- is granted to deal in this work without restriction, including un‐
-- limited rights to use, publicly perform, distribute, sell, modify,
-- merge, give away, or sublicence.
--
-- This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
-- the utmost extent permitted by applicable law, neither express nor
-- implied; without malicious intent or gross negligence. In no event
-- may a licensor, author or contributor be held liable for indirect,
-- direct, other damage, loss, or other issues arising in any way out
-- of dealing in the work, even if advised of the possibility of such
-- damage or existence of a defect, except proven that it results out
-- of said person’s immediate fault when using the work as intended.
-- -
-- Drop everything from the PostgreSQL database.
DO $$
DECLARE
r RECORD;
BEGIN
-- triggers
FOR r IN (SELECT pns.nspname, pc.relname, pt.tgname
FROM pg_trigger pt, pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace AND pc.oid=pt.tgrelid
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pt.tgisinternal=false
) LOOP
EXECUTE format('DROP TRIGGER %I ON %I.%I;',
r.tgname, r.nspname, r.relname);
END LOOP;
-- constraints #1: foreign key
FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
FROM pg_constraint pcon, pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pcon.contype='f'
) LOOP
EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
r.nspname, r.relname, r.conname);
END LOOP;
-- constraints #2: the rest
FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
FROM pg_constraint pcon, pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pcon.contype<>'f'
) LOOP
EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
r.nspname, r.relname, r.conname);
END LOOP;
-- indicēs
FOR r IN (SELECT pns.nspname, pc.relname
FROM pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pc.relkind='i'
) LOOP
EXECUTE format('DROP INDEX %I.%I;',
r.nspname, r.relname);
END LOOP;
-- normal and materialised views
FOR r IN (SELECT pns.nspname, pc.relname
FROM pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pc.relkind IN ('v', 'm')
) LOOP
EXECUTE format('DROP VIEW %I.%I;',
r.nspname, r.relname);
END LOOP;
-- tables
FOR r IN (SELECT pns.nspname, pc.relname
FROM pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pc.relkind='r'
) LOOP
EXECUTE format('DROP TABLE %I.%I;',
r.nspname, r.relname);
END LOOP;
-- sequences
FOR r IN (SELECT pns.nspname, pc.relname
FROM pg_class pc, pg_namespace pns
WHERE pns.oid=pc.relnamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pc.relkind='S'
) LOOP
EXECUTE format('DROP SEQUENCE %I.%I;',
r.nspname, r.relname);
END LOOP;
-- functions / procedures
FOR r IN (SELECT pns.nspname, pp.proname, pp.oid
FROM pg_proc pp, pg_namespace pns
WHERE pns.oid=pp.pronamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
) LOOP
EXECUTE format('DROP FUNCTION %I.%I(%s);',
r.nspname, r.proname,
pg_get_function_identity_arguments(r.oid));
END LOOP;
-- nōn-default schemata we own; assume to be run by a not-superuser
FOR r IN (SELECT pns.nspname
FROM pg_namespace pns, pg_roles pr
WHERE pr.oid=pns.nspowner
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'public')
AND pr.rolname=current_user
) LOOP
EXECUTE format('DROP SCHEMA %I;', r.nspname);
END LOOP;
-- voilà
RAISE NOTICE 'Database cleared!';
END; $$;
Testé sur PostgreSQL 9.6 (jessie-backports
). Les corrections de bogues et autres améliorations sont les bienvenues!
Si vous souhaitez nettoyer votre base de données nommée "example_db":
1) Connectez-vous à une autre base de données (par exemple, 'postgres'):
psql postgres
2) Supprimer votre base de données:
DROP DATABASE example_db;
3) Recréez votre base de données:
CREATE DATABASE example_db;