it-swarm.com.de

Postgres: Löschen Sie die gesamte Datenbank, bevor Sie sie aus dem Bash-Skript neu erstellen / auffüllen

Ich schreibe ein Shell-Skript (wird ein Cronjob), das:

1: Dump meine Produktionsdatenbank

2: Importiere den Dump in meine Entwicklungsdatenbank

Zwischen Schritt 1 und 2 muss die Entwicklungsdatenbank gelöscht werden (alle Tabellen löschen?). Wie geht das am besten mit einem Shell-Skript? Bisher sieht es so aus:

#!/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
108
Hoff

Ich würde einfach die Datenbank löschen und dann neu erstellen. Auf einem UNIX- oder Linux-System sollte dies folgendermaßen aussehen:

$ dropdb development_db_name
$ createdb developmnent_db_name

So mache ich das eigentlich.

161
Haes

Wenn Sie keine Sicherung der Datenbank benötigen, die im Nur-Text-SQL-Skriptdateiformat auf der Festplatte abgelegt wurde, können Sie pg_dump und pg_restore direkt zusammen über eine Pfeife.

Um Tabellen zu löschen und neu zu erstellen, können Sie das --clean Befehlszeilenoption für pg_dump SQL-Befehle zum Bereinigen (Löschen) von Datenbankobjekten vor dem Erstellen (der Befehle für) dieser Objekte ausgeben. (Dadurch wird nicht die gesamte Datenbank gelöscht, sondern nur jede Tabelle/Sequenz/Index/usw., bevor sie neu erstellt werden.)

Die obigen beiden würden ungefähr so ​​aussehen:

pg_dump -U username --clean | pg_restore -U username
84
Bandi-T

Obwohl die folgende Zeile aus einem Windows-Batch-Skript stammt, sollte der Befehl ziemlich ähnlich sein:

psql -U username -h localhost -d postgres -c "DROP DATABASE \"$DATABASE\";"

Mit diesem Befehl wird die gesamte Datenbank gelöscht, indem sie tatsächlich gelöscht wird. $DATABASE (In Windows sollte %DATABASE% Sein) in dem Befehl ist eine Windows-Umgebungsvariable, die als Datenbankname ausgewertet wird. Sie müssen dies durch Ihren development_db_name Ersetzen.

13
Frank Bollack

Zu entleeren:

pg_dump -Fc mydb > db.dump

Etwas wiederherstellen:

pg_restore --verbose --clean --no-acl --no-owner -h localhost -U myuser -d my_db db/latest.dump
7
Carlos Júlio

Ich habe verwendet:

pg_restore -c -d database_name filename.dump
6
Troy

Für die Fälle, in denen Sie nicht nur DROP SCHEMA public CASCADE;, DROP OWNED BY current_user; oder so, hier ist ein eigenständiges SQL-Skript, das ich geschrieben habe und das transaktionssicher ist (d. h. Sie können es zwischen BEGIN; und entweder ROLLBACK; zum Ausprobieren oder COMMIT;, um tatsächlich die Tat zu vollbringen) und "alle" Datenbankobjekte zu bereinigen ... nun, alle, die in der Datenbank verwendet werden, die unsere Anwendung verwendet, oder ich könnte sinnvoll hinzufügen, nämlich:

  • trigger auf Tabellen
  • einschränkungen für Tabellen (FK, PK, CHECK, UNIQUE)
  • indicēs
  • VIEWs (normal oder materialisiert)
  • tabellen
  • sequenzen
  • funktionen/Prozeduren ( pg_proc.proisagg wahrscheinlich sollte geehrt werden obwohl)
  • alle nicht standardmäßigen (d. h. nicht public oder DB-internen) Schemata, die „wir“ besitzen: Das Skript ist nützlich, wenn es als „kein Datenbank-Superuser“ ausgeführt wird. Ein Superuser kann all Schemata löschen (die wirklich wichtigen werden jedoch weiterhin explizit ausgeschlossen)

Nicht fallen gelassen werden (manche absichtlich; manche nur, weil ich kein Beispiel in unserer DB hatte):

  • das public -Schema (z. B. für durch Erweiterungen bereitgestellte Inhalte)
  • erweiterungen
  • aggregatfunktionen
  • kollatierungen und anderes lokales Material
  • ereignisauslöser
  • textsuchmaterial,… (siehe hier für andere Dinge, die ich möglicherweise verpasst habe)
  • rollen oder andere Sicherheitseinstellungen
  • zusammengesetzte Typen
  • toast-Tische
  • FDW und ausländische Tabellen

Ich habe auch eine Version, die "alles außer zwei Tabellen und was zu ihnen gehört" löscht, falls jemand interessiert ist. Der Unterschied ist klein. Kontaktieren Sie mich bei Bedarf.

Dies ist wirklich nützlich für den Fall, dass der Dump, den Sie wiederherstellen möchten, eine andere Version des Datenbankschemas hat (z. B. mit Debian dbconfig-common, Flyway oder Liquibase/DB-Manul) als die Datenbank, in der Sie sie wiederherstellen möchten.

SQL

-- 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; $$;

Getestet unter PostgreSQL 9.6 (jessie-backports). Bugfixes und weitere Verbesserungen sind willkommen!

2
mirabilos

Wenn Sie Ihre Datenbank mit dem Namen "example_db" bereinigen möchten:

1) Logge dich in eine andere Datenbank ein (zum Beispiel 'postgres'):

psql postgres

2) Entfernen Sie Ihre Datenbank:

DROP DATABASE example_db;

3) Erstellen Sie Ihre Datenbank neu:

CREATE DATABASE example_db;
1
Kamil Siwek