Wie kann ich alle Tabellen in einer PostgreSQL-Datenbank löschen?

1046

Wie kann ich alle Tabellen in PostgreSQL über die Befehlszeile löschen?

Ich möchte nicht die Datenbank selbst löschen, sondern nur alle Tabellen und alle darin enthaltenen Daten.

AP257
quelle
3
Über welche Befehlszeile sprechen Sie? Nach allem, was wir wissen, suchen Sie nach einer Windows PowerShell-Implementierung.
Greg Smith
4
Es tut uns leid. Arbeiten unter Unix, nachdem Sie 'psql' in die Befehlszeile eingegeben haben - also die psql-Befehlszeilenumgebung selbst.
AP257
101
DROP SCHEMA public CASCADE; - Schauder
Wildplasser
20
@ 0fnt müssen Sie 'CREATE SCHEMA public' machen; neue Tabellen wieder hinzuzufügen (auf die harte
Tour herausgefunden
4
Übrigens, wenn Sie fallen lassen public, verlieren Sie alle installierten Erweiterungen.
Sudo

Antworten:

1379

Wenn sich alle Ihre Tabellen in einem einzigen Schema befinden, könnte dieser Ansatz funktionieren (im folgenden Code wird davon ausgegangen, dass der Name Ihres Schemas lautet public).

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Wenn Sie PostgreSQL 9.3 oder höher verwenden, müssen Sie möglicherweise auch die Standardzuschüsse wiederherstellen.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Derek Slife
quelle
105
Beachten Sie, dass dadurch auch alle im öffentlichen Schema definierten Funktionen, Ansichten usw. gelöscht werden.
Brad Koch
5
Beachten Sie, dass dadurch die Systemtabellen (wie die, die mit beginnen pg_) nicht entfernt werden, da sie sich in einem anderen Schema befinden pg_catalog.
Congusbongus
36
Dadurch wird das Schema mit EIGENTÜMER erstellt, das auf den Benutzer festgelegt ist, unter dem Sie bei psql angemeldet sind. Dies führt zu Konflikten mit Anwendungen, die sich als anderer Benutzer anmelden. In diesem Fall müssen Sie auch "ALTER SCHEMA public OWNER to postgres" ausführen. (oder für jeden Benutzer, den Ihre App zum Erstellen von Tabellen verwendet)
mgojohn
13
Rufen Sie dies aus einer anderen Antwort auf, die Sie wahrscheinlich GRANT ALL ON SCHEMA public TO public;nach dem Erstellen haben möchten .
Federico
1
@Federico Warum willst du GRANT ALLnach dem Erstellen?
425nesp
410

Sie können eine Abfrage schreiben, um ein SQL-Skript wie folgt zu generieren:

select 'drop table "' || tablename || '" cascade;' from pg_tables;

Oder:

select 'drop table if exists "' || tablename || '" cascade;' from pg_tables;

Falls einige Tabellen aufgrund der Kaskadenoption in einem vorherigen Satz automatisch gelöscht werden.

Wie in den Kommentaren angegeben, möchten Sie die Tabellen, die Sie löschen möchten, möglicherweise nach Schemanamen filtern:

select 'drop table if exists "' || tablename || '" cascade;' 
  from pg_tables
 where schemaname = 'public'; -- or any other schema

Und dann lass es laufen.

Glorious COPY + PASTE wird auch funktionieren.

Pablo Santa Cruz
quelle
15
Ich denke, Sie meinten: Sie können eine Abfrage wie diese schreiben ... ... und dann die Ausgabe der Abfrage
ausführen
5
Wählen Sie 'Tabelle löschen, falls vorhanden "' || Tabellenname || '" Kaskade;' von pg_tables; stellt sicher, dass Tabellen mit Großbuchstaben ebenfalls ordnungsgemäß gelöscht werden.
Ivo van der Wijk
12
Die Klausel "where schemaname = 'public'", die LenW in seiner Antwort hinzugefügt hat, kann sehr nützlich sein, um den Löschbereich nur auf die von Ihnen verwaltete Datenbank und nicht auf die des Systems zu beschränken
Guillaume Gendre,
8
@jwg: auch, weil du manchmal nicht die Berechtigung dazu drop schema public cascade;hast, aber du hast fast immer die Berechtigung, Tabellen zu löschen .
Berkeley
2
Version für nicht öffentliche Schemas: Wählen Sie 'drop table falls vorhanden "' || schemaname || '". "' || tablename || '" cascade;' von pg_tables wobei schemaname = 'user_data';
Ludwig
292

Die am meisten akzeptierte Antwort zum Zeitpunkt dieses Schreibens (Januar 2014) lautet:

drop schema public cascade;
create schema public;

Dies funktioniert jedoch. Wenn Sie jedoch beabsichtigen, das öffentliche Schema in seinen ursprünglichen Zustand zurückzusetzen, wird die Aufgabe nicht vollständig ausgeführt. Wenn Sie unter pgAdmin III für PostgreSQL 9.3.1 auf das so erstellte "öffentliche" Schema klicken und im "SQL-Bereich" nachsehen, wird Folgendes angezeigt:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Im Gegensatz dazu wird eine brandneue Datenbank jedoch Folgendes enthalten:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public
  IS 'standard public schema';

Für mich verursachte die Verwendung eines Python-Webframeworks, das Datenbanktabellen (web2py) erstellt, wobei das erstere Probleme verursachte:

<class 'psycopg2.ProgrammingError'> no schema has been selected to create in 

Meiner Meinung nach lautet die völlig richtige Antwort:

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public IS 'standard public schema';

Um diese Befehle auch in pgAdmin III auszugeben, habe ich das Abfrage-Tool (Lupensymbol "Abritrary SQL-Abfragen ausführen") verwendet, oder Sie können Plugins-> PSQL Console verwenden

Hinweis

Wenn Sie Erweiterungen installiert haben, werden diese beim Löschen des Schemas gelöscht. Notieren Sie sich daher, was installiert werden muss, und führen Sie die erforderlichen Anweisungen aus. Z.B

CREATE EXTENSION postgis;

Benutzer
quelle
7
Bestätigt. Die zweizeilige Lösung ( dropdamals create) für PostgreSQL 9.1. Nach dem Upgrade auf 9.3 sind die beiden zusätzlichen granterforderlich.
Jinghao Shi
4
Noch eine Bestätigung: Mit Django habe ich den gleichen Fehler erhalten; Ich musste diese Zuschüsse ausführen, bevor Django mit der Datenbank interagieren konnte.
rjh
2
Dies funktionierte perfekt, außer dass ich auch einige Erweiterungen neu installieren musste: CREATE EXTENSION IF NOT EXISTS hstore; ERWEITERUNG ERSTELLEN, WENN NICHT pgcrypto vorhanden ist;
Shacker
173

Sie können alle Tabellen mit löschen

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

IMO ist dies besser als drop schema public, weil Sie nicht schemaalle Zuschüsse neu erstellen und wiederherstellen müssen.

Zusätzlicher Bonus, dass dies keine externe Skriptsprache oder das Kopieren von generiertem SQL zurück in den Interpreter erfordert.

Piotr Findeisen
quelle
4
Danke, dass du das gepostet hast! Ich konnte den drop schemaTrick nicht anwenden, da der Benutzer nicht Eigentümer des Schemas war, sondern nur der Tabellen. Dieser hat aber funktioniert :)
vdboor
Sehr sauber und spezifisch ... großartige Lösung, und sollte auch akzeptiert werden - Sie können sogar die where-Klausel hinzufügen, um die Tabellen
einzuschränken
Ich würde vorschlagen, diese Zeile folgendermaßen zu ändern EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; : EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger
@tyger Warum? Es sieht für mich nach einer unnötigen Komplikation aus. Gibt es eine Injektionsmöglichkeit (und behebt dies wirklich eine, wenn es eine gibt)? [Ich weiß nicht, ob Postgres dumm genug ist, Tabellennamen zuzulassen, um dies zu ermöglichen.] Wenn dies der Fall ist, sollten Sie Ihren Kommentar wirklich in eine Bearbeitung in der Antwort ändern (erklären, warum in den Bearbeitungskommentaren).
Auspex
@Auspex Heh, es war ein Problem mit der früheren Variante, als ich das tat. Ich kann mich
momentan
127

Wenn alles , was Sie wollen Drop ist im Besitz von demselben Benutzer, dann können Sie:

drop owned by the_user;

Dadurch wird alles gelöscht, was der Benutzer besitzt.

Dazu gehören materialisierte Ansichten, Ansichten, Sequenzen, Trigger, Schemata, Funktionen, Typen, Aggregate, Operatoren, Domänen usw. (also wirklich: alles ), die the_userbesitzen (= erstellt).

Sie müssen durch the_userden tatsächlichen Benutzernamen ersetzen. Derzeit gibt es keine Möglichkeit, alles für "den aktuellen Benutzer" zu löschen. Die kommende 9.5-Version wird die Option haben drop owned by current_user.

Weitere Details im Handbuch: http://www.postgresql.org/docs/current/static/sql-drop-owed.html

ein Pferd ohne Name
quelle
2
Dadurch wurden alle Schemas gelöscht, die dem Benutzer gehören (was ich nicht wollte).
Peter L
4
@PeterL: das ist klar im Handbuch dokumentiert, aber ich habe meinen Beitrag bearbeitet, um klar zu machen, dass "alles" wirklich alles
a_horse_with_no_name
Ich würde drop verwenden, das current_user gehört. Auf diese Weise müssen Sie sich nicht einmal um die Eingabe des richtigen Benutzernamens kümmern.
JavaGeek
2
Eigentlich eine sehr gute Lösung für mich. Meine Datenbank und mein publicSchema gehören postgres, aber alles andere gehört einem bestimmten Benutzer. Wenn Sie also alles löschen, was diesem Benutzer gehört, wird die Datenbank mit Ausnahme des Schemas gelöscht.
Auspex
Beachten Sie, dass in der Dokumentation angegeben ist, dass Berechtigungen widerrufen werden. Wenn Sie dies jedoch als normaler Benutzer ausführen, ist dies nicht möglich. Daher werden nur die Tabellen und dergleichen gelöscht, was genau das ist, was ich möchte. Nett!
ChetPrickles
76

Wie oben in Pablo beschrieben, um in Bezug auf den Fall einfach von einem bestimmten Schema abzuweichen:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';
LenW
quelle
Ich habe das benutzt, was für mich funktioniert hat. Ich nehme an, der where schemaname='public'Teil ist bedeutend?
ibic
1
@ibic Wenn Sie weglassen, dass Sie möglicherweise auch versuchen, alle internen Postgres-Tabellen zu löschen, ist dies höchstwahrscheinlich nicht das, was Sie wollen.
Whirlwin
49
drop schema public cascade;

sollte den Trick machen.

Joe Van Dyk
quelle
10
Beachten Sie, dass dadurch auch alle im öffentlichen Schema definierten Funktionen, Ansichten usw. gelöscht werden.
Joe Van Dyk
6
Außerdem müssen Sie danach erneut erstellen, um die Tabellen wieder mit hinzuzufügen CREATE SCHEMA public;. Siehe auch stackoverflow.com/a/14286370 für weitere Informationen
mikermcneil
29

Nach Pablo und LenW gibt es hier einen Einzeiler, der alles vorbereitet und dann ausführt:

psql -U $PGUSER $PGDB -t -c "select 'drop table \"' || tablename || '\" cascade;' from pg_tables where schemaname = 'public'" | psql -U $PGUSER $PGDB

NB: entweder setzen oder ersetzen $PGUSERund $PGDBmit den gewünschten Werten

Tim Diggins
quelle
22

Wenn Sie die prozedurale Sprache PL / PGSQL installiert haben , können Sie Folgendes verwenden, um alles ohne ein externes Shell / Perl-Skript zu entfernen.

DROP FUNCTION IF EXISTS remove_all();

CREATE FUNCTION remove_all() RETURNS void AS $$
DECLARE
    rec RECORD;
    cmd text;
BEGIN
    cmd := '';

    FOR rec IN SELECT
            'DROP SEQUENCE ' || quote_ident(n.nspname) || '.'
                || quote_ident(c.relname) || ' CASCADE;' AS name
        FROM
            pg_catalog.pg_class AS c
        LEFT JOIN
            pg_catalog.pg_namespace AS n
        ON
            n.oid = c.relnamespace
        WHERE
            relkind = 'S' AND
            n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
            pg_catalog.pg_table_is_visible(c.oid)
    LOOP
        cmd := cmd || rec.name;
    END LOOP;

    FOR rec IN SELECT
            'DROP TABLE ' || quote_ident(n.nspname) || '.'
                || quote_ident(c.relname) || ' CASCADE;' AS name
        FROM
            pg_catalog.pg_class AS c
        LEFT JOIN
            pg_catalog.pg_namespace AS n
        ON
            n.oid = c.relnamespace WHERE relkind = 'r' AND
            n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
            pg_catalog.pg_table_is_visible(c.oid)
    LOOP
        cmd := cmd || rec.name;
    END LOOP;

    FOR rec IN SELECT
            'DROP FUNCTION ' || quote_ident(ns.nspname) || '.'
                || quote_ident(proname) || '(' || oidvectortypes(proargtypes)
                || ');' AS name
        FROM
            pg_proc
        INNER JOIN
            pg_namespace ns
        ON
            (pg_proc.pronamespace = ns.oid)
        WHERE
            ns.nspname =
            'public'
        ORDER BY
            proname
    LOOP
        cmd := cmd || rec.name;
    END LOOP;

    EXECUTE cmd;
    RETURN;
END;
$$ LANGUAGE plpgsql;

SELECT remove_all();

Anstatt dies an der Eingabeaufforderung "psql" einzugeben, würde ich vorschlagen, dass Sie es in eine Datei kopieren und die Datei dann als Eingabe an psql mit den Optionen "--file" oder "-f" übergeben:

psql -f clean_all_pg.sql

Gutschrift, wo Gutschrift fällig ist: Ich habe die Funktion geschrieben, aber ich denke, die Anfragen (oder zumindest die erste) kamen von jemandem, der vor Jahren auf einer der pgsql-Mailinglisten stand. Ich erinnere mich nicht genau, wann oder welche.

Mark Lawrence
quelle
20

Wenn Sie trotzdem alle Tabellen nuklearisieren möchten, können Sie auf Feinheiten wie CASCADE verzichten, indem Sie alle Tabellen in einer einzigen Anweisung zusammenfassen. Dies beschleunigt auch die Ausführung.

SELECT 'TRUNCATE TABLE ' || string_agg('"' || tablename || '"', ', ') || ';' 
FROM pg_tables WHERE schemaname = 'public';

Direkt ausführen:

DO $$
DECLARE tablenames text;
BEGIN    
    tablenames := string_agg('"' || tablename || '"', ', ') 
        FROM pg_tables WHERE schemaname = 'public';
    EXECUTE 'TRUNCATE TABLE ' || tablenames;
END; $$

Bei Bedarf TRUNCATEdurch ersetzen DROP.

Beides beenden
quelle
1
Wenn Sie das publicSchema nicht bearbeiten, vergessen Sie nicht, den Schemanamen in den Ausdruck aufzunehmen: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')anstatt nur die Tabellennamen zu übergeben.
B12Toaster
15

Ich habe Pablos Antwort leicht geändert, um die generierten SQL-Befehle als eine einzige Zeichenfolge zurückzugeben:

select string_agg('drop table "' || tablename || '" cascade', '; ') 
from pg_tables where schemaname = 'public'
Adé
quelle
14

Verwenden Sie dieses Skript in pgAdmin:

DO $$
DECLARE 
    brow record;
BEGIN
    FOR brow IN (select 'drop table "' || tablename || '" cascade;' as table_name from pg_tables where schemaname = 'public') LOOP
        EXECUTE brow.table_name;
    END LOOP;
END; $$
Luca Perico
quelle
Das SQL ist für mich gescheitert. Ich habe SELECT concat ('drop table', Tabellenname, 'cascade;') AS drop_table_sql FROM pg_tables WHERE schemaname = 'public' verwendet
Keith John Hutchison
1
Muss etwas gewesen sein, was ich falsch gemacht habe, Luca. Ich habe es einfach noch einmal versucht und es hat funktioniert.
Keith John Hutchison
11

Nur für den Fall ... Einfaches Python-Skript, das die Postgresql-Datenbank bereinigt

import psycopg2
import sys

# Drop all tables from a given database

try:
    conn = psycopg2.connect("dbname='akcja_miasto' user='postgres' password='postgres'")
    conn.set_isolation_level(0)
except:
    print "Unable to connect to the database."

cur = conn.cursor()

try:
    cur.execute("SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_schema,table_name")
    rows = cur.fetchall()
    for row in rows:
        print "dropping table: ", row[1]   
        cur.execute("drop table " + row[1] + " cascade") 
    cur.close()
    conn.close()        
except:
    print "Error: ", sys.exc_info()[1]

Stellen Sie sicher, dass der Einzug nach dem Kopieren richtig ist, da Python darauf angewiesen ist.

Piotr Kochański
quelle
1
Werke zeichnen einen Charme aus. Ich habe dies ausgewählt, weil mir das Codieren der Datenbankverbindungsinformationen gefallen hat - das Letzte, was ich tun möchte, ist, die falsche Datenbank zu treffen! Außerdem ist meine Tabellenliste ein sich bewegendes Ziel.
JL Peyret
9

Mit der Funktion string_agg können Sie eine durch Kommas getrennte Liste erstellen, die sich perfekt für DROP TABLE eignet. Aus einem Bash-Skript:

#!/bin/bash
TABLES=`psql $PGDB -t --command "SELECT string_agg(table_name, ',') FROM information_schema.tables WHERE table_schema='public'"`

echo Dropping tables:${TABLES}
psql $PGDB --command "DROP TABLE IF EXISTS ${TABLES} CASCADE"
Jamie
quelle
sollte sollte #! / bin / sh sein
Gute Person
8

Wenn Sie Daten löschen möchten (keine Tabelle löschen):

-- Truncate tables and restart sequnces
SELECT 'TRUNCATE TABLE "' || table_schema || '"."' || table_name || '" RESTART IDENTITY CASCADE;' 
FROM information_schema.tables 
WHERE table_catalog = '<database>' AND table_schema = '<schema>';

Oder wenn Sie eine Drop-Tabelle möchten, können Sie diese SQL verwenden:

-- For tables
SELECT 'DROP TABLE "' || table_schema || '"."' || table_name || '" CASCADE;' 
FROM information_schema.tables 
WHERE table_catalog = '<database>' AND table_schema = '<schema>';

-- For sequences
SELECT 'DROP SEQUENCE d_a_seq "' || sequence_schema || '"."' || sequence_name || '";' 
FROM information_schema.sequences 
WHERE sequence_catalog = '<database>' AND sequence_schema = '<schema>';
Pooya
quelle
8

Hinweis: In meiner Antwort geht es darum, die Tabellen und andere Datenbankobjekte wirklich zu löschen. zum Löschen aller Daten in den Tabellen, dh Abschneiden aller Tabellen , hat Endre Both einen Monat später eine ähnlich gut ausgeführte Anweisung (direkte Ausführung) bereitgestellt.

Für die Fälle , in denen Sie nicht können DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;oder etwas, hier ist ein Stand-alone - SQL - Skript schrieb ich, die transaktionssicher ist (dh Sie es zwischen setzen können BEGIN;und entweder ROLLBACK;nur testen Sie es aus oder COMMIT;tatsächlich zu tun , die Tat) und Bereinigt "alle" Datenbankobjekte ... nun, alle, die in der Datenbank verwendet werden, die unsere Anwendung verwendet, oder ich könnte vernünftigerweise hinzufügen, nämlich:

  • Trigger auf Tabellen
  • Einschränkungen für Tabellen (FK, PK, CHECK,UNIQUE )
  • indicēs
  • VIEWs (normal oder materialisiert)
  • Tabellen
  • Sequenzen
  • Routinen (Aggregatfunktionen, Funktionen, Prozeduren)
  • Alle nicht standardmäßigen (dh nicht publicoder DB-internen) Schemata, die „wir“ besitzen: Das Skript ist nützlich, wenn es als „kein Datenbank-Superuser“ ausgeführt wird. Ein Superuser kann alle Schemata löschen (die wirklich wichtigen sind jedoch immer noch ausdrücklich ausgeschlossen).
  • Erweiterungen (vom Benutzer beigesteuert, aber ich lasse sie normalerweise absichtlich in)

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

  • das public Schema (z. B. für von Erweiterungen bereitgestellte Inhalte)
  • Kollatierungen und andere Gebietsschemata
  • Ereignisauslöser
  • Textsuche,… (siehe hier für andere Sachen, die ich vielleicht verpasst habe)
  • Rollen oder andere Sicherheitseinstellungen
  • zusammengesetzte Typen
  • Toasttische
  • FDW und fremde Tabellen

Dies ist sehr nützlich für Fälle, in denen der Dump, den Sie wiederherstellen möchten, eine andere Datenbankschemaversion aufweist (z. B. mit Debian)dbconfig-common , Flyway oder Liquibase / DB-Manul) als die Datenbank, in der Sie ihn wiederherstellen möchten.

Ich habe auch eine Version, die "alles außer zwei Tabellen und was dazu gehört" löscht (eine Sequenz, manuell getestet, sorry, ich weiß, langweilig), falls jemand interessiert ist; Der Unterschied ist klein. Kontaktieren Sie mich oder überprüfen Sie dieses Repo bei Interesse.

SQL

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

Getestet, mit Ausnahme späterer Ergänzungen ( extensionsbeigesteuert von Clément Prévost ), auf PostgreSQL 9.6 ( jessie-backports). Die Aggregatentfernung wurde unter 9.6 und 12.2 getestet, die Verfahrensentfernung ebenfalls unter 12.2. Bugfixes und weitere Verbesserungen sind willkommen!

Mirabilos
quelle
Das obige Skript enthält Fehler, da es nicht zwischen Funktionen und Prozeduren unterscheidet: Fehler bei DROP FUNCTIONeiner Prozedur und umgekehrt. Ich habe den Funktionsabschnitt folgendermaßen geändert: AND pp.prokind ='f' -- FunctionoderAND pp.prokind ='p' -- Procedure
BogeyMan
1
@BogeyMan Das ist kein Fehler, das Auslassen von Aggregatfunktionen wurde dokumentiert und das Skript wurde dokumentiert, um nur auf 9.6 getestet zu werden. Aber ich habe mir Ihren Kommentar zu Herzen genommen und ihn angepasst, um Aggregate ( proisagg) auf ≤ 10.x und Aggregate und Prozeduren ( prokind) auf ≥ 11 (dynamisch überprüft) zu behandeln, und beide getestet ☻ danke für den Hinweis.
Mirabilos
8

Dies ist eine wirklich interessante Frage, die Sie auf mehrere Arten erledigen können. Ich hoffe, das wird Ihnen nützlich sein.

  1. Durch Löschen und Neuerstellen des aktuellen Schemas

Hier haben wir im Allgemeinen publicstandardmäßig ein Schema. Also benutze ich es als Instanz.

DROP SCHEMA `public` CASCADE;
CREATE SCHEMA `public`;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;

Wenn Sie PostgreSQL 9.3 oder höher verwenden, müssen Sie möglicherweise auch die Standardzuschüsse wiederherstellen.

Vorteile:

Dadurch wird ein gesamtes Schema bereinigt und als neues Schema neu erstellt.

Nachteile:

Sie werden andere Einheiten verlieren auch wie Functions, Views, Materialized viewsusw.

  1. Durch Abrufen aller Tabellennamen aus der pg_tablesTabelle.

PostgreSQL speichert alle Tabellen in seiner Datensatztabelle mit dem Namen pg_table.

SELECT
  'DROP TABLE IF EXISTS "' || tablename || '" CASCADE;' 
from
  pg_tables WHERE schemaname = 'public';

Wie Sie sehen können, können wir mithilfe von Unterabfragen die gesamten Tabellen aus dem Schema entfernen.

Vorteile:

Wenn die anderen Datenentitäten wichtig sind und Sie nur Tabellen aus dem Schema löschen möchten, ist dieser Ansatz für Sie sehr hilfreich.

Mayur
quelle
6

Sie müssen Tabellen und Sequenzen löschen, hier ist, was für mich funktioniert hat

psql -qAtX -c "select 'DROP TABLE IF EXISTS ' || quote_ident(table_schema) || '.' || quote_ident(table_name) || ' CASCADE;' FROM information_schema.tables where table_type = 'BASE TABLE' and not table_schema ~ '^(information_schema|pg_.*)$'" | psql -qAtX
psql -qAtX -c "select 'DROP SEQUENCE IF EXISTS ' || quote_ident(relname) || ' CASCADE;' from pg_statio_user_sequences;" | psql -qAtX

bevor Sie den Befehl ausführen müssen Sie sudo / su den postgresBenutzer oder (Export Anschlussdetails PGHOST, PGPORT, PGUSERund PGPASSWORD) und dannexport PGDATABASE=yourdatabase

Muayyad Alsadi
quelle
5

Rake-Task für Rails zum Zerstören aller Tabellen in der aktuellen Datenbank

namespace :db do
  # rake db:drop_all_tables
  task drop_all_tables: :environment do
    query = <<-QUERY
      SELECT
        table_name
      FROM
        information_schema.tables
      WHERE
        table_type = 'BASE TABLE'
      AND
        table_schema NOT IN ('pg_catalog', 'information_schema');
    QUERY

    connection = ActiveRecord::Base.connection
    results    = connection.execute query

    tables = results.map do |line|
      table_name = line['table_name']
    end.join ", "

    connection.execute "DROP TABLE IF EXISTS #{ tables } CASCADE;"
  end
end
der Lehrer
quelle
1
Es könnte einfacher / sicherer sein, AND table_schema = 'public' zu sagen, anstatt NICHT IN dieser Liste.
Steve
Aus irgendeinem Grund wurde mein Schema mit aufgefüllten Daten erstellt. Dieser Rechen funktioniert. Also mache rake db:createich es danach. Sie können den Steve-Tipp machen und den Code entfernen table_name = und ", "für ","und #{ tables }für#{tables}
Washington Botelho
5

Die folgenden Schritte können hilfreich sein (für Linux-Benutzer):

  1. Geben Sie zunächst die postgresEingabeaufforderung mit folgendem Befehl ein:

    sudo -u postgres psql
  2. Geben Sie die Datenbank mit diesem Befehl ein (mein Datenbankname ist :) maoss:

    \c maoss
  3. Geben Sie nun den Befehl zum Löschen aller Tabellen ein:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
FaridLU
quelle
1
Befolgen Sie die Schritte auf meinem Ubuntu 19.04, es hat einwandfrei funktioniert!
Alexandru-Mihai Manolescu
1
@FaridLU Hat mir sehr geholfen, danke!
Justin Wood
4

Ich habe die Bash-Methode von Jamie erweitert, indem ich mich um Ansichten gekümmert habe, da er nur den Tabellentyp "Basistabelle" berücksichtigt, der die Standardeinstellung ist.

Der folgende Bash-Code löscht zuerst die Ansichten und dann den Rest

#!/usr/bin/env bash

PGDB="yourDB"
# By exporting user & pass your dont need to interactively type them on execution
export PGUSER="PGusername"
export PGPASSWORD="PGpassword"

VIEWS=`psql -d $PGDB -t --command "SELECT string_agg(table_name, ',') FROM information_schema.tables WHERE table_schema='public' AND table_type='VIEW'"`
BASETBLS=`psql -d $PGDB -t --command "SELECT string_agg(table_name, ',') FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'"`

echo Dropping views:${VIEWS}
psql $PGDB --command "DROP VIEW IF EXISTS ${VIEWS} CASCADE"
echo Dropping tables:${BASETBLS}
psql $PGDB --command "DROP TABLE IF EXISTS ${BASETBLS} CASCADE"
martinseener
quelle
Tolles Drehbuch ... habe es einfach benutzt und wie ein Zauber funktioniert. Ich habe auch eine Zeile für Sequenzen hinzugefügt: SEQUENCES =psql -d $PGDB -t --command "SELECT string_agg(sequence_name, ',') FROM information_schema.sequences WHERE sequence_schema='public' AND sequence_catalog='$PGDB'"
raminr
4

in einer Windows-Batchdatei:

@echo off
FOR /f "tokens=2 delims=|" %%G IN ('psql --host localhost --username postgres --command="\dt" YOUR_TABLE_NAME') DO (
   psql --host localhost --username postgres --command="DROP table if exists %%G cascade" sfkb
   echo table %%G dropped
)
Lewis
quelle
2

Nun, da ich gerne von der Kommandozeile aus arbeite ...

psql -U <user> -d <mydb> -c '\dt' | cut -d ' ' -f 4 | sed -e "s/^/drop table if exists /" | sed -e "s/$/;/"

-c '\dt' ruft den Befehl list tables auf.

List of relations Schema | Name | Type | Owner --------+-------------------+-------+---------- public | _d_psidxddlparm | table | djuser public | _d_psindexdefn | table | djuser

cut -d ' ' -f 4 Leiten Sie nun die Ausgabe weiter, um das 4. Feld (bei Verwendung von Leerzeichen als Trennzeichen) zu erfassen, bei dem es sich um die Tabelle handelt.

sedwird dann verwendet, um drop tabledem ;Befehlstrennzeichen ein Präfix und ein Suffix hinzuzufügen.

| egrep '_d_'- Pipe es in grepetwas mehr und Sie können selektiver sein, welche Tabellen Sie fallen lassen.

drop table if exists _d_psidxddlparm; drop table if exists _d_psindexdefn;

Hinweis: Wie geschrieben, werden dadurch falsche Zeilen für die \dtBefehlsausgabe von Spaltenüberschriften und Gesamtzeilen am Ende generiert . Ich vermeide das durch Greppen, aber du könntest headund verwenden tail.

JL Peyret
quelle
2

Am einfachsten ist es, das öffentliche Schema zu löschen, wie andere in früheren Antworten vorgeschlagen haben. Dies ist jedoch kein guter Weg. Sie wissen nie, was mit dem öffentlichen Schema geschehen ist, das inzwischen vergessen und nicht dokumentiert wurde. Sie wissen auch nicht, ob dies in Zukunft genauso funktionieren wird. In V9 wäre es in Ordnung gewesen, aber in V10 würden alle Benutzer den Zugriff auf das Schema verlieren und müssen erneut Zugriff erhalten, sonst wird Ihre Anwendung beschädigt. Ich habe V11 nicht überprüft, aber der Punkt ist, dass Sie nie wissen, was beim Wechsel von Maschine zu Maschine, Site zu Site oder Version zu Version kaputt geht. Dies ist auch nicht möglich, wenn Sie ein Benutzer sind, der Zugriff auf die Datenbank hat, jedoch nicht auf das Schema.

Wenn Sie dies programmgesteuert tun müssen, decken andere Antworten dies ab, aber eine Sache, die die obigen Antworten nicht berücksichtigen, ist, Postgres zu veranlassen, die Arbeit für Sie zu erledigen. Wenn Sie pg_dump mit der folgenden Option -c verwenden:

sudo su postgres -c "pg_dump -U postgres WhateverDB -c -f "/home/Anyone/DBBackupWhateverDB-ServerUnscheduled.sql""

Dadurch wird ein DB-Wiederherstellungsskript mit SQL-Anweisungen erstellt, mit dem alle Tabellen gelöscht werden.

Wenn der einzige Zweck beim Stellen der Frage darin bestand, die Tabellen vor der Wiederherstellung zu löschen, erledigt Ihre Wiederherstellung die Arbeit für Sie.

Wenn Sie es jedoch für etwas anderes benötigen, können Sie die drop-Anweisungen einfach aus dem SQL-Skript kopieren.

RichardP
quelle