Jak mogę upuścić wszystkie tabele w bazie danych PostgreSQL?


1041

Jak mogę upuścić wszystkie tabele w PostgreSQL, pracując z wiersza poleceń?

I nie chcą spadać samej bazy danych, tylko wszystkie tabele i wszystkie dane w nich.


3
O jakiej linii poleceń mówisz? Z tego, co wiemy, szukasz implementacji Windows PowerShell.
Greg Smith

4
Przepraszam. Pracując na Uniksie, po wpisaniu „psql” w wierszu poleceń - tak samo środowisko wiersza polecenia psql.
AP257,

101
SCHEMAT DROP public CASCADE; - drżenie
wildplasser

20
@ 0fnt musisz zrobić „UTWÓRZ SCHEMAT publiczny”; aby ponownie dodać nowe tabele (dowiedziałem się na
własnej skórze

4
BTW, kiedy upuścisz public, stracisz wszystkie zainstalowane rozszerzenia.
sudo

Odpowiedzi:


1374

Jeśli wszystkie tabele są w jednym schemacie, to podejście może działać (poniższy kod zakłada, że ​​nazwa Twojego schematu to public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Jeśli używasz PostgreSQL w wersji 9.3 lub nowszej, może być konieczne przywrócenie domyślnych dotacji.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;

105
Pamiętaj, że spowoduje to również usunięcie wszystkich funkcji, widoków itp. Zdefiniowanych w schemacie publicznym.
Brad Koch

5
Zauważ, że nie usunie tabele systemowe (takie jak te, które zaczynają się pg_), ponieważ są one w innym schemacie pg_catalog.
congusbongus

36
Spowoduje to utworzenie schematu w / OWNER dla użytkownika zalogowanego do psql jako. Spowoduje to konflikt z aplikacjami, które logują się jako inny użytkownik. W takim przypadku musisz także uruchomić „ZMIENIĆ SCHEMAT publiczny WŁAŚCICIEL do postgres;” (lub
każdemu

13
Przywołując to z innej odpowiedzi, którą prawdopodobnie chcesz mieć GRANT ALL ON SCHEMA public TO public;po utworzeniu.
Federico,

1
@Federico Dlaczego chcesz GRANT ALLpo utworzeniu?
425nesp

408

Możesz napisać zapytanie, aby wygenerować skrypt SQL w następujący sposób:

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

Lub:

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

W przypadku, gdy niektóre tabele są automatycznie usuwane z powodu opcji kaskadowej w poprzednim zdaniu.

Ponadto, jak stwierdzono w komentarzach, możesz filtrować tabele, które chcesz upuścić według nazwy schematu:

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

A potem uruchom.

Chwalebna KOPIA + WKLEJ również będzie działać.


15
Myślę, że miałeś na myśli: możesz napisać takie zapytanie ... ... a następnie uruchomić wynik zapytania
Vinko Vrsalovic

5
wybierz „drop table, jeśli istnieje” ”|| tablename ||” „kaskada”; z pg_tables; upewni się, że tabele z dużymi literami również zostaną poprawnie upuszczone.
Ivo van der Wijk,

12
klauzula „gdzie schemaname = 'public'”, którą LenW dodał w swojej odpowiedzi, może być bardzo przydatna do ograniczenia zakresu usuwania tylko do bazy danych, którą zarządzasz, a nie do bazy danych systemu
Guillaume Gendre,

8
@jwg: także dlatego, że czasami nie masz uprawnień drop schema public cascade;, ale prawie zawsze masz uprawnienia do usuwania tabel.
berkes

2
Wersja dla schematów niepublicznych: wybierz „upuść tabelę, jeśli istnieje” ”|| schemaname ||” „.” ”|| tablename ||” „cascade;” z pg_tables gdzie schemaname = 'user_data';
ludwig

291

Najbardziej akceptowaną odpowiedzią na ten tekst (styczeń 2014) jest:

drop schema public cascade;
create schema public;

Działa to, jednak jeśli Twoim celem jest przywrócenie schematu publicznego do stanu pierwotnego, nie jest to w pełni możliwe. W pgAdmin III dla PostgreSQL 9.3.1 kliknięcie utworzonego w ten sposób schematu „publicznego” i spojrzenie w „okienku SQL” spowoduje wyświetlenie następujących informacji:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Natomiast dla zupełnie nowej bazy danych będą:

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

Dla mnie za pomocą frameworka sieci web Python, który tworzy tabele bazy danych (web2py), użycie tego pierwszego spowodowało problemy:

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

Moim zdaniem w pełni poprawna odpowiedź brzmi:

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

Pamiętaj też, aby wydać te polecenia w pgAdmin III, użyłem narzędzia Query (ikona lupy „Wykonaj abritrary SQL queries”) lub możesz użyć Plugins-> PSQL Console

Uwaga

Jeśli masz zainstalowane jakieś rozszerzenia, zostaną one usunięte po upuszczeniu schematu, więc powinieneś zanotować, co potrzebujesz zainstalować, a następnie wykonać instrukcje w razie potrzeby. Na przykład

CREATE EXTENSION postgis;


7
Potwierdzony. Dwuliniowe rozwiązanie ( dropwówczas create) działało na PostgreSQL 9.1. Po aktualizacji do 9.3 grantkonieczne są dwa dodatkowe .
Jinghao Shi

4
Jeszcze jedno potwierdzenie: używając Django, dostałem ten sam błąd; Musiałem uruchomić te granty, zanim django będzie mogło współpracować z bazą danych.
rjh

2
Działa to idealnie, z tym wyjątkiem, że musiałem również ponownie zainstalować niektóre rozszerzenia: UTWÓRZ ROZSZERZENIE, JEŚLI NIE ISTNIEJE hstore; UTWÓRZ PRZEDŁUŻENIE, JEŚLI NIE ISTNIEJE pgcrypto;
shacker

173

Możesz upuścić wszystkie tabele za pomocą

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 jest to lepsze niż drop schema public, ponieważ nie trzeba odtwarzać schemai przywracać wszystkich dotacji.

Dodatkowa premia za to, że nie wymaga zewnętrznego języka skryptowego ani wklejania kopii wygenerowanego SQL z powrotem do interpretera.


4
Dziękujemy za opublikowanie tego! Nie mogłem użyć tej drop schemasztuczki, ponieważ użytkownik nie był właścicielem schematu, tylko tabel. Ten zadziałał :)
vdboor

Bardzo czyste i specyficzne ... świetne rozwiązanie, które również powinno zostać zaakceptowane - możesz nawet dodać do klauzuli where, aby ograniczyć tabele, które chcesz zachować, tak jak w tych wymaganych przez rozszerzenia takie jak PostGIS ...
DPSSpatial

Sugerowałbym zmianę tej linii EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; w ten sposób: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger

@tyger Dlaczego? Dla mnie wygląda to na niepotrzebną komplikację. Czy istnieje możliwość wstrzyknięcia (i czy tak naprawdę to naprawia, jeśli istnieje)? [Nie wiem, czy Postgres jest na tyle głupi, by pozwolić na to, aby nazwy tabeli umożliwiały to] Jeśli tak, naprawdę powinieneś zmienić swój komentarz na edycję w odpowiedzi (wyjaśniając dlaczego w komentarzach do edycji).
Auspex

@Auspex Heh, to był problem z poprzednim wariantem, kiedy to robiłem. Nie pamiętam teraz ...
tyger

127

Jeśli wszystko, co chcesz upuścić, jest własnością tego samego użytkownika, możesz użyć:

drop owned by the_user;

Spowoduje to usunięcie wszystkiego , co użytkownik jest właścicielem.

Obejmuje to zmaterializowane widoki, widoki, sekwencje, wyzwalacze, schematy, funkcje, typy, agregacje, operatory, domeny i tak dalej (tak naprawdę: wszystko ), do którego należy the_user(= utworzono).

Musisz zastąpić the_userrzeczywistą nazwą użytkownika, obecnie nie ma opcji, aby porzucić wszystko dla „bieżącego użytkownika”. Nadchodząca wersja 9.5 będzie miała opcję drop owned by current_user.

Więcej szczegółów w instrukcji: http://www.postgresql.org/docs/current/static/sql-drop-owned.html


2
Spowodowało to usunięcie wszystkich schematów należących do użytkownika (czego nie chciałem robić).
Peter L,

4
@PeterL: co jest wyraźnie udokumentowane w instrukcji, ale zredagowałem swój post, aby wyjaśnić, że „wszystko” naprawdę oznacza wszystko
a_horse_with_no_name

Chciałbym użyć drop należącego do current_user; W ten sposób nie musisz się nawet martwić o wpisanie poprawnej nazwy użytkownika.
JavaGeek

2
Właściwie to bardzo dobre rozwiązanie dla mnie. Moja baza danych i publicschemat są własnością postgres, ale wszystko inne jest własnością określonego użytkownika, więc usunięcie wszystkiego, co należy do tego użytkownika, usuwa bazę danych oprócz schematu.
Auspex

Zauważ, że dokumentacja mówi, że cofnie uprawnienia, ale jeśli uruchomisz to jako zwykły użytkownik, nie może, więc po prostu upuszcza tabele i tym podobne, co jest dokładnie tym, czego chcę. Miły!
ChetPrickles

76

Zgodnie z Pablo powyżej, aby po prostu usunąć z określonego schematu, w odniesieniu do przypadku:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';

Użyłem tego, co działało dla mnie. Zakładam, że ta where schemaname='public'część jest znacząca?
ibic

1
@ibic Jeśli pominiesz możliwość potencjalnego usunięcia wszystkich wewnętrznych tabel postgres, co najprawdopodobniej nie jest tym, czego chcesz.
whirlwin

49
drop schema public cascade;

powinien załatwić sprawę.


10
Pamiętaj, że spowoduje to również usunięcie wszystkich funkcji, widoków itp. Zdefiniowanych w schemacie publicznym.
Joe Van Dyk

6
ponadto będziesz musiał ponownie utworzyć ponownie, aby dodać tabele z powrotem CREATE SCHEMA public;. Zobacz także stackoverflow.com/a/14286370, aby uzyskać więcej informacji
mikermcneil,

29

Podążając za Pablo i LenW, oto jedna linijka, która robi wszystko, zarówno przygotowując, jak i wykonując:

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

Uwaga: ustaw lub zamień $PGUSERoraz $PGDBz żądanymi wartościami


22

Jeśli masz zainstalowany język proceduralny PL / PGSQL , możesz użyć następującego polecenia, aby usunąć wszystko bez zewnętrznego skryptu powłoki / Perla.

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();

Zamiast wpisywać to w wierszu polecenia „psql”, sugerowałbym skopiowanie go do pliku, a następnie przekazanie pliku jako danych wejściowych do psql przy użyciu opcji „--file” lub „-f”:

psql -f clean_all_pg.sql

Kredyt tam, gdzie należy się kredyt: napisałem tę funkcję, ale myślę, że zapytania (lub przynajmniej pierwsze) pochodziły od kogoś z jednej z list mailingowych pgsql lata temu. Nie pamiętam dokładnie, kiedy i który z nich.


20

Jeśli i tak chcesz nuke wszystkie tabele, możesz zrezygnować z subtelności, takich jak CASCADE, umieszczając wszystkie tabele w jednym wyciągu. To także przyspiesza wykonanie.

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

Wykonując to bezpośrednio:

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

Wymień TRUNCATEsię DROPstosownie.


1
gdy nie działa na publicschemacie, nie zapomnij dołączyć nazwy schematu do wyrażenia: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')zamiast zwykłego przekazywania nazw tabel.
B12Toaster

15

Zmodyfikowałem nieco odpowiedź Pablo, aby dla wygody wygenerowane polecenia SQL były zwracane jako jeden ciąg:

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

14

Użyj tego skryptu w 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; $$

To sql dla mnie nie powiodło się. Użyłem SELECT concat ('drop table', tablename, 'cascade;') AS drop_table_sql OD pg_tables GDZIE schemaname = 'public'
Keith John Hutchison

1
To musiało być coś, co zrobiłem źle, Luca. Właśnie spróbowałem ponownie i zadziałało.
Keith John Hutchison

11

Na wszelki wypadek ... Prosty skrypt Pythona, który czyści bazę danych Postgresql

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]

Upewnij się, że po skopiowaniu wcięcie jest prawidłowe, ponieważ Python na nim polega.


1
działa na urok. Wybrałem to, ponieważ lubiłem zakodować na stałe informacje o połączeniu z bazą danych - ostatnią rzeczą, którą chcę zrobić, jest trafienie w niewłaściwą bazę danych! a także moja lista tabel jest ruchomym celem.
JL Peyret

9

Możesz użyć funkcji string_agg, aby utworzyć listę oddzieloną przecinkami, idealną do TABELI KROPEK. Ze skryptu bash:

#!/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"

powinno być #! / bin / sh
Good Person

8

Jeśli chcesz usunąć dane (nie usuwać tabeli):

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

Lub jeśli chcesz drop table, możesz użyć tej sql:

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

8

Uwaga: moja odpowiedź dotyczy naprawdę usuwania tabel i innych obiektów bazy danych; do usuwania wszystkich danych w tabelach, czyli obcięcie wszystkich tabel , Endre Zarówno dostarczył Podobnie dobrze wykonane (bezpośrednia realizacja) oświadczenie miesiąc później.

Dla przypadków, w których nie możesz po prostu DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;lub coś, oto samodzielny skrypt SQL, który napisałem, który jest bezpieczny dla transakcji (tj. Możesz umieścić go pomiędzy BEGIN;i albo ROLLBACK;po prostu przetestować, albo COMMIT;faktycznie zrobić czyn) i czyści „wszystkie” obiekty bazy danych… cóż, wszystkie te używane w bazie danych, z której korzysta nasza aplikacja, lub mógłbym rozsądnie dodać, czyli:

  • wyzwalacze na stołach
  • ograniczenia w tabelach (FK, PK, CHECK, UNIQUE)
  • indicēs
  • VIEWs (normalny lub zmaterializowany)
  • stoły
  • sekwencje
  • procedury (funkcje agregujące, funkcje, procedury)
  • wszystkie schematy nōn-default (tj. nie publiclub wewnętrzne DB) „my” są właścicielami: skrypt jest użyteczny, gdy działa jako „nie superużytkownik bazy danych”; superużytkownikiem może spaść wszystkie schematy (to naprawdę ważne te są nadal wyraźnie wyłączone, chociaż)
  • Rozszerzenia (user-przyczyniły ale zwykle celowo pozostawić je w)

Nie spadła są (niektóre celowe, niektóre tylko dlatego, że nie miał przykładu w naszym DB):

  • publicschematu (np przesuwnych warunkiem rzeczy w nich)
  • zestawienia i inne ustawienia regionalne
  • wyzwalacze zdarzeń
  • Wyszukiwanie tekstowe rzeczy ... (patrz tutaj dla innych rzeczy mógłbym pominąć)
  • role lub inne ustawienia zabezpieczeń
  • typy kompozytowe
  • stoły tostowe
  • Tabele FDW i zagraniczne

Jest to naprawdę przydatne w przypadkach, gdy zrzut, który chcesz przywrócić, ma inną wersję schematu bazy danych (np. Z Debianem dbconfig-common, Flyway lub Liquibase / DB-Manul) niż baza danych, w której chcesz go przywrócić.

Mam też wersję, która usuwa „wszystko oprócz dwóch tabel i tego, co do nich należy” (sekwencja, przetestowana ręcznie, przepraszam, wiem, nudna) na wypadek, gdyby ktoś był zainteresowany; różnica jest niewielka. Skontaktuj się ze mną lub sprawdź to repozytorium, jeśli jesteś zainteresowany.

SQL

-- Copyright © 2019, 2020
--      mirabilos <t.glaser@tarent.de>
--
-- 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; $$;

Testowane, z wyjątkiem późniejszych dodatków ( napisanychextensions przez Clément Prévost ), na PostgreSQL 9.6 ( jessie-backports). Usuwanie kruszywa testowane na 9.6 i 12.2, usuwanie procedury również testowane na 12.2. Mile widziane poprawki i dalsze ulepszenia!


W powyższym skrypcie występują błędy, ponieważ nie rozróżnia on funkcji i procedur: procedura DROP FUNCTIONkończy się niepowodzeniem i na odwrót. Zmodyfikowałem sekcję funkcji do tego: AND pp.prokind ='f' -- FunctionlubAND pp.prokind ='p' -- Procedure
BogeyMan

1
@BogeyMan To nie jest błąd, pominięcie funkcji agregujących zostało udokumentowane, a skrypt udokumentowany do przetestowania tylko na wersji 9.6. Ale wziąłem twój komentarz do serca i dostosowałem go do obsługi agregatów ( proisagg) na ≤ 10.x oraz agregatów i procedur ( prokind) na ≥ 11 (sprawdzane dynamicznie) i przetestowałem oba ☻ dzięki za podpowiedź.
mirabilos

8

To naprawdę interesujące pytanie, a wykonasz je na wiele sposobów. Mam nadzieję, że ci się przyda.

  1. Po upuszczeniu i odtworzeniu bieżącego schematu

Tutaj, ogólnie, publicdomyślnie mamy schemat. Używam tego jako instancji.

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

Jeśli używasz PostgreSQL w wersji 9.3 lub nowszej, może być konieczne przywrócenie domyślnych dotacji.

Plusy:

Spowoduje to wyczyszczenie całego schematu i odtworzenie go jako nowego.

Cons:

Stracisz też inne podmioty jak Functions, Views, Materialized views, itd.

  1. Korzystając z pobierania wszystkich nazw pg_tablestabel z tabeli.

PostgreSQL przechowuje wszystkie tabele w tabeli rekordów o nazwie pg_table.

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

Jak widać, za pomocą podzapytania możemy usunąć całe tabele ze schematu.

Plusy:

Gdy inne jednostki danych są ważne i chcesz po prostu usunąć tylko tabele ze schematu, takie podejście naprawdę ci się przyda.


6

Musisz upuścić tabele i sekwencje, oto co dla mnie zadziałało

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

przed uruchomieniem polecenia może trzeba sudo / su do postgresużytkownika lub (połączenie eksport szczegółów PGHOST, PGPORT, PGUSERi PGPASSWORD), a następnieexport PGDATABASE=yourdatabase


5

Zadanie rake dla Railsów w celu zniszczenia wszystkich tabel w bieżącej bazie danych

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

1
Może być łatwiej / bezpieczniej powiedzieć AND table_schema = 'public' niż NOT IN tej listy.
Steve

Z jakiegoś powodu mój schemat został utworzony z zapełnionymi danymi. Ta grabie działa. Więc po zrobie rake db:createto uruchamiam Można zrobić końcówkę Steve i usunąć kod table_name = i zmiany ", "na ","i #{ tables }fo#{tables}
Washington Botelho

4

Ulepszyłem metodę bash od jamie, dbając o widoki, ponieważ tylko szanuje on typ tabeli „tabela podstawowa”, która jest domyślna.

następujący kod bash usuwa najpierw widoki, a następnie całą resztę

#!/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"

Świetny skrypt ... właśnie go użyłem i działał jak urok. Dodałem również wiersz dla sekwencji: 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

w pliku wsadowym Windows:

@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
)

4

Pomocne mogą być następujące kroki (dla użytkowników Linuksa):

  1. Najpierw wpisz postgreswiersz polecenia, wykonując następujące polecenie:

    sudo -u postgres psql
  2. Wejdź do bazy danych za pomocą tego polecenia (moja nazwa bazy danych to maoss:):

    \c maoss
  3. Teraz wpisz polecenie upuszczenia wszystkich tabel:

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

1
postępowałem zgodnie ze wskazówkami na moim Ubuntu 19.04, działało bezbłędnie!
Alexandru-Mihai Manolescu

1
@FaridLU Bardzo pomogłem, dzięki!
Justin Wood

2

cóż, ponieważ lubię pracować z wiersza poleceń ...

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

-c '\dt' wywoła polecenie listy tabel.

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

cut -d ' ' -f 4 teraz potokuj wyjście, aby chwycić czwarte pole (gdy używasz spacji jako separatora), którym jest tabela.

sedjest następnie używany do prefiksu a drop tablei sufiksu ;separatora poleceń.

| egrep '_d_'- Pipe to do grepkilku więcej i możesz być bardziej selektywny, co do upuszczanych tabel.

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

Uwaga: jak napisano, wygeneruje to fałszywe wiersze dla danych \dtwyjściowych poleceń nagłówków kolumn i sumy wierszy na końcu. Unikam tego przez grepowanie, ale możesz użyć headi tail.


2

Najprostszym sposobem jest usunięcie schematu publicznego, jak sugerowali inni w poprzednich odpowiedziach. Jednak to NIE jest dobry sposób. Nigdy nie wiadomo, co zostało zrobione ze schematem publicznym, który został zapomniany i nie został udokumentowany. Nie wiesz też, czy to zadziała w przyszłości. W wersji V9 wszystko byłoby w porządku, ale w wersji 10 wszyscy użytkownicy straciliby dostęp do schematu i muszą uzyskać dostęp ponownie, w przeciwnym razie aplikacja się zepsuje. Nie sprawdziłem wersji V11, ale chodzi o to, że nigdy nie wiesz, co się zepsuje podczas przechodzenia od maszyny do maszyny, witryny do witryny lub wersji do wersji. Nie można tego również zrobić, jeśli użytkownik ma dostęp do bazy danych, ale nie do schematu.

Jeśli musisz to zrobić programowo, wówczas powyższe odpowiedzi obejmują inne odpowiedzi, ale jedną z powyższych odpowiedzi nie są rozważenia, aby zachęcić Postgres do wykonania pracy za Ciebie. Jeśli używasz pg_dump z opcją -c jak poniżej:

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

Spowoduje to utworzenie skryptu przywracania DB z instrukcjami SQL, które usuwają wszystkie tabele.

Jeśli jedynym celem zadania pytania było usunięcie tabel przed przywróceniem, wówczas przywrócenie wykona pracę za Ciebie.

Jeśli jednak potrzebujesz go do czegoś innego, możesz po prostu skopiować instrukcje drop ze skryptu sql.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.