J'ai créé un nouveau db db à partir d'un serveur de production avec le --data-only
et --column-inserts
flags, donc je n'ai qu'un tas d'instructions d'insertion pour insérer des données lors d'une restauration sur un serveur intermédiaire.
pg_dump -h localhost -U adminuser --data-only --column-inserts maindb > maindb.sql
Comment puis-je supprimer toutes les données de la base de données du serveur de transfert avant de restaurer les données à partir du vidage de production?
Je veux supprimer toutes les données uniquement afin de ne pas avoir à supprimer et à créer la base de données et tout ça. Je veux juste supprimer des données et insérer de nouvelles données, c'est tout.
Je n'ai pas la possibilité de supprimer et de créer la base de données pour plusieurs raisons. Je vais devoir supprimer toutes les données et les insérer uniquement, donc tout ce qu'il faut pour trouver comment faire, je suis prêt à y aller, mais j'ai évidemment besoin d'aide pour commencer.
J'ai également besoin d'automatiser ce processus. Automatisera le "vidage des données de la base de données de production", puis "la suppression des données sur la base de données intermédiaire", puis "la restauration des données vers la base de données intermédiaire". J'ai juste besoin d'aide sur la partie "suppression de données sur la base de données intermédiaire".
Je cours sur PostgreSQL 9.5.2
Vous n'avez pas besoin de supprimer la base de données, il devrait suffire de supprimer tous les objets dans la base de données. Cela peut être fait en utilisant
drop owned by adminuser
Si vous créez ensuite le vidage SQL comprenant le create table
instructions (donc sans les --data-only
option) tout devrait bien se passer.
Vous pouvez également supprimer le --column-inserts
alors, ce qui accélérera l'importation lot.
Cependant, si vous voulez tout supprimer, vous pouvez le faire avec un peu de SQL dynamique:
do
$$
declare
l_stmt text;
begin
select 'truncate ' || string_agg(format('%I.%I', schemaname, tablename), ',')
into l_stmt
from pg_tables
where schemaname in ('public');
execute l_stmt;
end;
$$
Cela tronquera toutes les tables du schéma public
avec une seule instruction qui fonctionnera également même s'il existe de nombreuses contraintes de clé étrangère reliant toutes les tables. Si vos tables sont réparties sur plusieurs schémas, vous devez les ajouter dans la condition where
.
pg_restore a un indicateur --clean (ou éventuellement --create) qui supprimera automatiquement les données avant d'exécuter les opérations.
L'excellente documentation devrait vous aider grandement ...
Juste pour clarifier, au cas où cela prêterait à confusion:
Nettoyez (supprimez) les objets de la base de données avant de les recréer. (À moins que --si existe existe, cela peut générer des messages d'erreur inoffensifs, si aucun objet n'était présent dans la base de données de destination.)
Cela ne supprimera pas la base de données réelle .. uniquement les tables/vues/etc.
Si, pour une raison quelconque, la suppression et la recréation des tables ne sont pas acceptables, vous devrez mettre plus de travail pour créer manuellement un script qui crée un data only
vidage à partir de la base de données source, émet TRUNCATE
ou DELETE
dans la base de données cible, puis charge le vidage des données. Pour autant que je sache, il n'y a pas de façon rapide/simple de le faire.
SELECT 'TRUNCATE ' || input_table_name || ' CASCADE;' AS truncate_query FROM(SELECT table_schema || '.' || table_name AS input_table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') AND table_schema NOT LIKE 'pg_toast%') AS information;
La requête ci-dessus générera des requêtes tronquées pour toutes les tables de la base de données.
Remarque: ma réponse consiste à supprimer réellement les tables et autres objets de base de données; pour suppression de toutes les données in les tables, c'est-à-dire la troncature de toutes les tables , Endre Both a fourni une déclaration également bien exécutée (exécution directe) un mois plus tard.
Pour les cas où vous ne pouvez pas simplement DROP SCHEMA public CASCADE;
, DROP OWNED BY current_user;
ou quelque chose comme ça, voici un script SQL autonome que j'ai écrit, qui est sûr pour les transactions (c'est-à-dire que vous pouvez le mettre entre BEGIN;
et soit ROLLBACK;
pour le tester ou COMMIT;
pour faire l'acte) et nettoie "tous" les objets de la base de données… enfin, tous ceux utilisés dans la base de données que notre application utilise ou je pourrais raisonnablement ajouter, ce qui est:
CHECK
, UNIQUE
)VIEW
s (normal ou matérialisé)public
ou DB-internal) "que nous" possédons: le script est utile lorsqu'il est exécuté comme "pas un superutilisateur de base de données"; un superutilisateur peut supprimer tous les schémas (les plus importants sont toujours explicitement exclus, cependant)Non abandonnés sont (certains délibérés; certains uniquement parce que je n'avais aucun exemple dans notre DB):
public
(par exemple pour les éléments fournis par l'extension)C'est vraiment utile dans les cas où le vidage que vous souhaitez restaurer est d'une version de schéma de base de données différente (par exemple avec Debian dbconfig-common
, Flyway ou Liquibase/DB-Manul) que la base de données dans laquelle vous souhaitez le restaurer.
J'ai également une version qui supprime "tout sauf deux tables et ce qui leur appartient" (une séquence, testée manuellement, désolé, je sais, ennuyeuse) au cas où quelqu'un serait intéressé; le diff est petit. Contactez-moi ou vérifiez ce dépôt si vous êtes intéressé.
-- Copyright © 2019, 2020
-- 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
q TEXT;
r RECORD;
BEGIN
-- triggers
FOR r IN (SELECT pns.nspname, pc.relname, pt.tgname
FROM pg_catalog.pg_trigger pt, pg_catalog.pg_class pc, pg_catalog.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_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.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_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.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_catalog.pg_class pc, pg_catalog.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_catalog.pg_class pc, pg_catalog.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_catalog.pg_class pc, pg_catalog.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_catalog.pg_class pc, pg_catalog.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;
-- extensions (only if necessary; keep them normally)
FOR r IN (SELECT pns.nspname, pe.extname
FROM pg_catalog.pg_extension pe, pg_catalog.pg_namespace pns
WHERE pns.oid=pe.extnamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
) LOOP
EXECUTE format('DROP EXTENSION %I;', r.extname);
END LOOP;
-- aggregate functions first (because they depend on other functions)
FOR r IN (SELECT pns.nspname, pp.proname, pp.oid
FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns, pg_catalog.pg_aggregate pagg
WHERE pns.oid=pp.pronamespace
AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND pagg.aggfnoid=pp.oid
) LOOP
EXECUTE format('DROP AGGREGATE %I.%I(%s);',
r.nspname, r.proname,
pg_get_function_identity_arguments(r.oid));
END LOOP;
-- routines (functions, aggregate functions, procedures, window functions)
IF EXISTS (SELECT * FROM pg_catalog.pg_attribute
WHERE attrelid='pg_catalog.pg_proc'::regclass
AND attname='prokind' -- PostgreSQL 11+
) THEN
q := 'CASE pp.prokind
WHEN ''p'' THEN ''PROCEDURE''
WHEN ''a'' THEN ''AGGREGATE''
ELSE ''FUNCTION''
END';
ELSIF EXISTS (SELECT * FROM pg_catalog.pg_attribute
WHERE attrelid='pg_catalog.pg_proc'::regclass
AND attname='proisagg' -- PostgreSQL ≤10
) THEN
q := 'CASE pp.proisagg
WHEN true THEN ''AGGREGATE''
ELSE ''FUNCTION''
END';
ELSE
q := '''FUNCTION''';
END IF;
FOR r IN EXECUTE 'SELECT pns.nspname, pp.proname, pp.oid, ' || q || ' AS pt
FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns
WHERE pns.oid=pp.pronamespace
AND pns.nspname NOT IN (''information_schema'', ''pg_catalog'', ''pg_toast'')
' LOOP
EXECUTE format('DROP %s %I.%I(%s);', r.pt,
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_catalog.pg_namespace pns, pg_catalog.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é, sauf ajouts ultérieurs (extensions
apporté par Clément Prévost ), sur PostgreSQL 9.6 (jessie-backports
). Suppression d'agrégats testée sur 9.6 et 12.2, retrait de procédure également testé sur 12.2. Les corrections de bugs et autres améliorations sont les bienvenues!