Come posso eliminare tutte le tabelle in un database PostgreSQL?


1047

Come posso eliminare tutte le tabelle in PostgreSQL, lavorando dalla riga di comando?

Io non voglio far cadere il database stesso, a tutte le tabelle e tutti i dati in essi contenuti.


3
Di quale riga di comando stai parlando? Per quanto ne sappiamo, stai cercando un'implementazione di Windows PowerShell.
Greg Smith,

4
Scusate. Lavorando su Unix, dopo aver digitato 'psql' nella riga di comando, quindi l'ambiente della riga di comando psql stesso.
AP257,

101
DROP SCHEMA CASCADE pubblica; - brivido
wildplasser

20
@ 0fnt dovrai fare 'CREATE SCHEMA public;' per aggiungere nuovamente nuove tabelle (scoperto nel modo più difficile)
nym

4
A proposito, quando si rilascia public, si perde qualsiasi estensione installata.
sudo,

Risposte:


1382

Se tutte le tabelle sono in un unico schema, questo approccio potrebbe funzionare (il codice seguente presuppone che il nome dello schema sia public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Se si utilizza PostgreSQL 9.3 o versioni successive, potrebbe essere necessario ripristinare le sovvenzioni predefinite.

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

105
Notare che ciò eliminerà anche tutte le funzioni, le viste, ecc. Definite nello schema pubblico.
Brad Koch,

5
Si noti che questo non rimuoverà le tabelle di sistema (come quelli che iniziano con pg_) come sono in uno schema diverso, pg_catalog.
congusbongus,

36
Questo creerà lo schema con il PROPRIETARIO impostato sull'utente con il quale si è effettuato l'accesso a psql. Ciò andrà in conflitto con le applicazioni che accedono come un altro utente. In tal caso, devi anche eseguire "ALTER SCHEMA PROPRIETARIO pubblico su postgres;" (oa qualsiasi utente utilizzato dalla tua app per creare tabelle)
mgojohn,

13
Visualizzalo da un'altra risposta che probabilmente vorresti avere GRANT ALL ON SCHEMA public TO public;dopo la creazione.
Federico

1
@Federico Perché vorresti GRANT ALLdopo la creazione?
425nesp

410

È possibile scrivere una query per generare uno script SQL come questo:

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

O:

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

Nel caso in cui alcune tabelle vengano automaticamente eliminate a causa dell'opzione a cascata in una frase precedente.

Inoltre, come indicato nei commenti, potresti voler filtrare le tabelle che desideri eliminare in base al nome dello schema:

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

E poi eseguirlo.

Glorious COPY + PASTE funzionerà anche.


15
Penso che volevi dire: puoi scrivere una query come questa ... ... E poi eseguire l'output della query
Vinko Vrsalovic

5
seleziona 'drop table se esiste "' || tablename || '" cascade;' da pg_tables; farà in modo che anche le tabelle con le maiuscole vengano eliminate correttamente.
Ivo van der Wijk,

12
la clausola "where schemaname = 'public'" che LenW ha aggiunto nella sua risposta può essere molto utile per ridurre l'ambito di cancellazione solo al database che hai gestito e non a quelli del sistema
Guillaume Gendre,

8
@jwg: inoltre, perché a volte non hai i permessi drop schema public cascade;, ma quasi sempre hai i permessi per eliminare le tabelle.
Berkes,

2
Versione per schemi non pubblici: selezionare 'drop table se esiste "' || schemaname || '". "' || tablename || '" cascade;' da pg_tables dove schemaname = 'user_data';
Ludwig,

292

La risposta più accettata al momento della stesura di questo scritto (gennaio 2014) è:

drop schema public cascade;
create schema public;

Questo funziona, tuttavia se la tua intenzione è di ripristinare lo schema pubblico al suo stato vergine, ciò non compie completamente l'attività. In pgAdmin III per PostgreSQL 9.3.1, se fai clic sullo schema "pubblico" creato in questo modo e guardi nel "riquadro SQL", vedrai quanto segue:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Tuttavia, al contrario, un database nuovo di zecca avrà il seguente:

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

Per me utilizzo un framework web Python che crea tabelle di database (web2py), usando i primi problemi causati:

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

Quindi, a mio avviso, la risposta pienamente corretta è:

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

Nota anche per emettere questi comandi in pgAdmin III, ho usato lo strumento Query (icona lente di ingrandimento "Esegui query SQL abritrary") oppure potresti usare Plugin-> Console PSQL

Nota

Se sono installate estensioni, queste verranno eliminate quando si rilascia lo schema, quindi è necessario prendere nota di ciò che è necessario installare e quindi eseguire le istruzioni necessarie. Per esempio

CREATE EXTENSION postgis;


7
Confermato. La soluzione a due linee ( dropallora create) funzionava su PostgreSQL 9.1. Dopo l'aggiornamento a 9.3, i due extra grantsono necessari.
Jinghao Shi,

4
Ancora una conferma: usando Django ho avuto lo stesso errore; Prima di interagire con il database, avevo bisogno di eseguire quei contributi.
rjh

2
Funzionava perfettamente, tranne per il fatto che avevo anche bisogno di reinstallare alcune estensioni: CREATE EXTENSION SE NON ESISTE hstore; CREA ESTENSIONE SE NON ESISTE pgcrypto;
shacker

173

Puoi eliminare tutte le tabelle con

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 questo è meglio di drop schema public, perché non è necessario ricreare schemae ripristinare tutte le sovvenzioni.

Bonus aggiuntivo che questo non richiede un linguaggio di scripting esterno, né copia e incolla di SQL generato di nuovo all'interprete.


4
Grazie per aver pubblicato questo! Non ho potuto usare ildrop schema trucco in quanto l'utente non era il proprietario dello schema, ma solo delle tabelle. Questo ha funzionato però :)
vdboor

Molto pulita e specifica ... ottima soluzione, e dovrebbe essere anche accettata - puoi anche aggiungere alla clausola where per limitare le tabelle che vuoi conservare, come in quelle necessarie per estensioni come PostGIS ...
DPSSpatial

Vorrei suggerire di cambiare quella linea EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; con questo: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger

@tyger Perché? Mi sembra una complicazione inutile. C'è una possibilità di iniezione (e questo risolve davvero uno se c'è)?[Non so se Postgres sia abbastanza sciocco da permettere ai nomi delle tabelle di renderlo possibile] Se c'è, dovresti davvero cambiare il tuo commento in una modifica nella risposta (spiegando perché nei commenti di modifica).
Auspex,

@Auspex Heh, è ​​stato un problema con l'ex variante quando lo stavo facendo. Non riesco a ricordare in questo momento ...
tyger

127

Se tutto ciò che desideri eliminare è di proprietà dello stesso utente, puoi utilizzare:

drop owned by the_user;

Questo lascerà cadere tutto ciò che l'utente possiede.

Ciò include viste materializzate, viste, sequenze, trigger, schemi, funzioni, tipi, aggregati, operatori, domini e così via (così, davvero: tutto ) che the_userpossiede (= creato).

Devi sostituire the_usercon il nome utente effettivo, al momento non esiste alcuna opzione per eliminare tutto per "l'utente corrente". La prossima versione 9.5 avrà l'opzione drop owned by current_user.

Maggiori dettagli nel manuale: http://www.postgresql.org/docs/current/static/sql-drop-owned.html


2
Questo ha lasciato cadere tutti gli schemi di proprietà dell'utente (cosa che non volevo fare).
Peter L

4
@PeterL: che è chiaramente documentato nel manuale, ma ho modificato il mio post per chiarire che "tutto" significa davvero tutto
a_horse_with_no_name

Vorrei utilizzare drop di proprietà di current_user; In questo modo non dovrai nemmeno preoccuparti di digitare il nome utente corretto.
JavaGeek

2
In realtà un'ottima soluzione per me. Il mio database e lo publicschema sono di proprietà di postgres, ma tutto il resto è di proprietà di un utente specifico, quindi l'eliminazione di tutto ciò che appartiene a tale utente cancella il database ad eccezione dello schema.
Auspex,

Nota che la documentazione dice che revocherà i privilegi, ma se lo esegui come un normale utente non può, quindi lascia cadere le tabelle e simili, che è esattamente quello che voglio. Bello!
ChetPrickles,

76

Come da Pablo sopra, per cadere da uno schema specifico, rispetto al caso:

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

Ho usato questo, che ha funzionato per me. Presumo che la where schemaname='public'parte sia significativa?
ibic

1
@ibic Se lasci che potresti potenzialmente provare a cancellare anche tutte le tabelle interne di Postgres, che probabilmente non è quello che desideri.
Whirlwin

49
drop schema public cascade;

dovrebbe fare il trucco.


10
Notare che ciò eliminerà anche tutte le funzioni, le viste, ecc. Definite nello schema pubblico.
Joe Van Dyk,

6
inoltre dovrai ricreare di nuovo in seguito per aggiungere nuovamente le tabelle CREATE SCHEMA public;. Vedere anche stackoverflow.com/a/14286370 per ulteriori informazioni
mikermcneil

29

Seguendo Pablo e LenW, ecco un one-liner che fa tutto sia preparando che poi eseguendo:

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

NB: impostare o sostituire $PGUSERe $PGDBcon i valori desiderati


22

Se è installato il linguaggio procedurale PL / PGSQL, è possibile utilizzare quanto segue per rimuovere tutto senza uno script esterno shell / Perl.

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

Invece di digitare questo al prompt "psql", suggerirei di copiarlo in un file e quindi passare il file come input a psql utilizzando le opzioni "--file" o "-f":

psql -f clean_all_pg.sql

Credito dove è dovuto il credito: ho scritto la funzione, ma penso che le domande (o almeno la prima) siano arrivate da qualcuno su una delle mailing list di pgsql anni fa. Non ricordare esattamente quando o quale.


20

Se vuoi comunque cancellare tutte le tabelle, puoi fare a meno di cose come CASCADE mettendo tutte le tabelle in una singola istruzione. Questo rende anche l'esecuzione più rapida.

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

Eseguendolo direttamente:

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

Sostituire TRUNCATEcon DROPcome applicabile.


1
quando non si opera sullo publicschema, non dimenticare di includere il nome dello schema nell'espressione: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')invece di passare semplicemente i nomi delle tabelle.
B12,

15

Ho modificato leggermente la risposta di Pablo per la comodità di avere i comandi SQL generati restituiti come un'unica stringa:

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

14

Usa questo script 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; $$

Quel sql fallito per me. Ho usato SELECT concat ('drop table', tablename, 'cascade;') AS drop_table_sql FROM pg_tables WHERE schemaname = 'public'
Keith John Hutchison,

1
Deve essere stato qualcosa di sbagliato, Luca. Ho appena provato di nuovo e ha funzionato.
Keith John Hutchison,

11

Per ogni evenienza ... Script Python semplice che pulisce il database 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]

Assicurati che dopo averlo copiato il rientro sia corretto poiché Python si basa su di esso.


1
le opere rivestono un fascino. Ho scelto questo perché mi piaceva codificare le informazioni sulla connessione db - l'ultima cosa che voglio fare è colpire il db sbagliato! e, inoltre, il mio elenco di tabelle è un obiettivo mobile.
JL Peyret,

9

È possibile utilizzare la funzione string_agg per creare un elenco separato da virgole, perfetto per DROP TABLE. Da uno script 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"

dovrebbe essere #! / bin / sh
Brava persona,

8

Se si desidera eliminare i dati (non eliminare la tabella):

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

Oppure, se vuoi una tabella a discesa, puoi usare questo 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

Nota: la mia risposta riguarda davvero l'eliminazione delle tabelle e di altri oggetti del database; per eliminare tutti i dati nelle tabelle, ovvero troncare tutte le tabelle , Endre Both ha fornito un'istruzione altrettanto ben eseguita (esecuzione diretta) un mese dopo.

Per i casi in cui non puoi semplicemente DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;o qualcosa del genere, ecco uno script SQL autonomo che ho scritto, che è sicuro per le transazioni (cioè puoi metterlo tra BEGIN;e o ROLLBACK;semplicemente testarlo o COMMIT;fare effettivamente l'atto) e pulisce "tutti" gli oggetti del database ... beh, tutti quelli utilizzati nel database che la nostra applicazione utilizza o che potrei aggiungere sensatamente, che è:

  • si innesca sui tavoli
  • vincoli sulle tabelle (FK, PK, CHECK,UNIQUE )
  • Indici
  • VIEWs (normale o materializzato)
  • tavoli
  • sequenze
  • routine (funzioni aggregate, funzioni, procedure)
  • tutti gli schemi nōn-default (cioè no publico DB-internal) "noi" possediamo: lo script è utile quando eseguito come "non un superutente del database"; un superutente può eliminare tutti gli schemi (quelli veramente importanti sono comunque esplicitamente esclusi)
  • estensioni (fornite dall'utente ma normalmente le lascio deliberatamente)

Non vengono rilasciati (alcuni deliberati; alcuni solo perché non avevo un esempio nel nostro DB):

  • lo publicschema (ad es. per contenuti forniti dall'estensione in essi)
  • collazioni e altre cose locali
  • trigger di eventi
  • ricerca di testo, ... (vedi qui per altre cose che potrei aver perso)
  • ruoli o altre impostazioni di sicurezza
  • tipi compositi
  • tavoli toast
  • FDW e tavoli stranieri

Questo è veramente utile per i casi in cui il dump che si desidera ripristinare ha una versione dello schema del database diversa (ad es. Con Debiandbconfig-common , Flyway o Liquibase / DB-Manul) rispetto al database in cui si desidera ripristinarlo.

Ho anche una versione che elimina "tutto tranne due tabelle e ciò che appartiene a loro" (una sequenza, testata manualmente, scusate, lo so, noioso) nel caso qualcuno fosse interessato; il diff è piccolo. Contattatemi o controllate questo repository se interessati.

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

Testato, tranne aggiunte successive ( extensionsfornite da Clément Prévost ), su PostgreSQL 9.6 ( jessie-backports). Rimozione aggregata testata su 9.6 e 12.2, rimozione della procedura testata anche su 12.2. Bugfix e ulteriori miglioramenti sono benvenuti!


Ci sono errori nello script sopra perché non distingue tra funzioni e procedure: DROP FUNCTIONfallisce per una procedura e viceversa. Ho modificato la sezione delle funzioni in questo modo: AND pp.prokind ='f' -- FunctionoppureAND pp.prokind ='p' -- Procedure
BogeyMan il

1
@BogeyMan Questo non è un errore, l'omissione di funzioni aggregate è stata documentata e lo script è stato documentato per essere testato solo su 9.6. Ma ho preso a cuore il tuo commento e l'ho adattato per gestire aggregati ( proisagg) su ≤ 10.x e aggregati e procedure ( prokind) su ≥ 11 (controllato dinamicamente) e testato entrambi ☻ grazie per il suggerimento.
mirabilos

8

Questa è una domanda davvero interessante, e lo farai in diversi modi. Spero che questo ti sia utile.

  1. Rilasciare e ricreare lo schema corrente

Qui, in generale, abbiamo uno publicschema di default. Quindi, lo sto usando come istanza.

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

Se si utilizza PostgreSQL 9.3 o versioni successive, potrebbe essere necessario ripristinare le sovvenzioni predefinite.

Professionisti:

Questo pulirà un intero schema e lo ricreare come nuovo.

Contro:

Perderai altri enti anche come Functions, Views, Materialized views, etc.

  1. Utilizzando il recupero di tutti i nomi di pg_tablestabella dalla tabella.

PostgreSQL memorizza tutte le tabelle nella sua tabella record denominata pg_table.

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

Come puoi vedere, Usando la subquery, possiamo rimuovere le intere tabelle dallo schema.

Professionisti:

Quando le altre entità di dati sono importanti e desideri eliminare solo le tabelle dallo schema, questo approccio ti sarà davvero utile.


6

Devi eliminare tabelle e sequenze, ecco cosa ha funzionato per me

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

prima di eseguire il comando potrebbe essere necessario sudo / su per le postgresutente o (collegamento esportazione dettagli PGHOST, PGPORT, PGUSERe PGPASSWORD) e poiexport PGDATABASE=yourdatabase


5

Attività di rake per Rails per distruggere tutte le tabelle nel database corrente

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
Potrebbe essere più semplice / sicuro dire AND table_schema = 'public' piuttosto che NON IN QUESTO elenco.
Steve,

Per qualche ragione il mio schema è stato creato con dati popolati. Questo rastrello funziona. Quindi, dopo rake db:createaverlo eseguito, lo eseguo. Puoi dare la mancia a Steve e rimuovere il codice table_name = e cambiare ", "per ","e #{ tables }per#{tables}
Washington Botelho

5

I seguenti passaggi potrebbero essere utili (per utenti Linux):

  1. Inizialmente inserisci il postgresprompt dei comandi con il comando seguente:

    sudo -u postgres psql
  2. Immettere il database con questo comando (il mio nome di database è:) maoss:

    \c maoss
  3. Ora inserisci il comando per eliminare tutte le tabelle:

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

1
ho seguito i passaggi sul mio Ubuntu 19.04, ha funzionato perfettamente!
Alexandru-Mihai Manolescu,

1
@FaridLU Aiutato molto, grazie!
Justin Wood,

4

Ho migliorato il metodo bash da jamie occupandomi delle viste perché rispetta solo il tipo di tabella "tabella di base" che è l'impostazione predefinita.

il seguente codice bash elimina prima le visualizzazioni e poi tutto il resto

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

Ottima sceneggiatura ... l'ho appena usata e ha funzionato come un fascino. Ho anche aggiunto una riga per le sequenze: 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 un file batch di 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
)

2

bene, dal momento che mi piace lavorare dalla riga di comando ...

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

-c '\dt' invocherà il comando list table.

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

cut -d ' ' -f 4 ora, reindirizza il suo output per afferrare il quarto campo (quando usi lo spazio come separatore), che è la tabella.

sedviene quindi utilizzato per aggiungere il prefisso a drop tablee il suffisso per il ;separatore dei comandi.

| egrep '_d_'- Inseriscilo in un greppo 'di più e puoi essere più selettivo su quali tabelle rilasciare.

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

Nota: come scritto, questo genererà righe fasulle per l' \dtoutput dei comandi delle intestazioni di colonna e delle righe totali alla fine. Lo evito grepping, ma potresti usare heade tail.


2

Il modo più semplice è eliminare lo schema pubblico come altri hanno suggerito nelle risposte precedenti. Tuttavia, questo NON è un buon modo. Non si sa mai cosa è stato fatto allo schema pubblico che è stato da allora dimenticato e non documentato. Inoltre, non sai se funzionerà allo stesso modo in futuro. In V9, sarebbe andato tutto bene, ma in V10 tutti gli utenti avrebbero perso l'accesso allo schema e gli sarebbe stato nuovamente concesso l'accesso, altrimenti l'applicazione si interromperà. Non ho controllato V11, ma il punto è che non si sa mai cosa si romperà mentre si passa da una macchina all'altra, da un sito all'altro o da una versione all'altra. Inoltre, non può essere eseguito se si è un utente che ha accesso al database, ma non allo schema.

Se hai bisogno di farlo a livello di codice, allora altre risposte sopra lo riguardano, ma una cosa che le risposte sopra non considerano è quella di convincere Postgres a fare il lavoro per te. Se usi pg_dump con l'opzione -c come di seguito:

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

Ciò creerà uno script di ripristino del DB con istruzioni sql che elimineranno tutte le tabelle.

Se l'unico scopo nel porre la domanda era eliminare le tabelle prima del ripristino, il ripristino farà il lavoro per te.

Tuttavia, se ne hai bisogno per qualcos'altro, puoi semplicemente copiare le istruzioni di rilascio dallo script sql.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.