Comment supprimer toutes les tables d'une base de données PostgreSQL?

1047

Comment puis-je supprimer toutes les tables dans PostgreSQL, à partir de la ligne de commande?

Je ne veux pas supprimer la base de données elle-même, juste toutes les tables et toutes les données qu'elles contiennent .

AP257
la source
3
De quelle ligne de commande parlez-vous? Pour tout ce que nous savons, vous recherchez une implémentation de Windows PowerShell.
Greg Smith
4
Désolé. Travailler sous Unix, après avoir tapé 'psql' sur la ligne de commande - donc l'environnement de ligne de commande psql lui-même.
AP257
101
DROP SCHEMA public CASCADE; - frisson
wildplasser
20
@ 0fnt vous devrez faire 'CREATE SCHEMA public;' ajouter de nouvelles tables à nouveau (découvert à la dure)
nym
4
BTW, lorsque vous supprimez public, vous perdez toutes les extensions installées.
sudo

Réponses:

1382

Si toutes vos tables sont dans un seul schéma, cette approche pourrait fonctionner (le code ci-dessous suppose que le nom de votre schéma est public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Si vous utilisez PostgreSQL 9.3 ou supérieur, vous devrez peut-être également restaurer les autorisations par défaut.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Derek Slife
la source
105
Notez que cela supprimera également toutes les fonctions, vues, etc. définies dans le schéma public.
Brad Koch
5
Notez que cela ne supprimera pas les tables système (comme ceux qui commencent par pg_) comme dans un schéma différent, pg_catalog.
congusbongus
36
Cela créera le schéma avec OWNER défini pour l'utilisateur auquel vous êtes connecté en tant que psql. Cela entraînera un conflit avec les applications qui se connectent en tant qu'utilisateur différent. Dans ce cas, vous devez également exécuter "ALTER SCHEMA public OWNER to postgres;" (ou à tout utilisateur que votre application utilise pour créer des tables)
mgojohn
13
Pour en revenir à une autre réponse, vous voudrez probablement en avoir GRANT ALL ON SCHEMA public TO public;après la création.
Federico
1
@Federico Pourquoi voudriez-vous GRANT ALLaprès la création?
425nesp
410

Vous pouvez écrire une requête pour générer un script SQL comme celui-ci:

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

Ou:

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

Dans le cas où certaines tables sont automatiquement supprimées en raison de l'option en cascade dans une phrase précédente.

En outre, comme indiqué dans les commentaires, vous souhaiterez peut-être filtrer les tables que vous souhaitez supprimer par nom de schéma:

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

Et puis lancez-le.

Glorious COPY + PASTE fonctionnera également.

Pablo Santa Cruz
la source
15
Je pense que vous vouliez dire: Vous pouvez écrire une requête comme celle-ci ... ... Et puis exécuter la sortie de la requête
Vinko Vrsalovic
5
sélectionnez 'drop table if exist "' || tablename || '" cascade;' de pg_tables; s'assurera que les tables en majuscules sont également correctement supprimées.
Ivo van der Wijk
12
la clause «où schemaname = 'public'» que LenW a ajouté dans sa réponse peut être très utile pour réduire la portée de la suppression à la base de données que vous avez gérée et non à celle du système
Guillaume Gendre
8
@jwg: aussi, parce que parfois vous n'avez pas l'autorisation de le faire drop schema public cascade;, mais vous avez presque toujours les autorisations pour supprimer des tables.
berkes
2
Version pour les schémas non publics: sélectionnez 'drop table if exist "' || schemaname || '". "' || tablename || '" cascade;' de pg_tables où schemaname = 'user_data';
ludwig
292

La réponse la plus acceptée à ce jour (janvier 2014) est:

drop schema public cascade;
create schema public;

Cela fonctionne, cependant, si votre intention est de restaurer le schéma public à son état vierge, cela n'accomplit pas entièrement la tâche. Sous pgAdmin III pour PostgreSQL 9.3.1, si vous cliquez sur le schéma "public" créé de cette façon et regardez dans le "volet SQL", vous verrez ce qui suit:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Cependant, en revanche, une nouvelle base de données aura les éléments suivants:

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

Pour moi, en utilisant un framework web python qui crée des tables de base de données (web2py), en utilisant les premiers problèmes causés:

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

Donc, à mon avis, la réponse entièrement correcte est:

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

Notez également que pour émettre ces commandes dans pgAdmin III, j'ai utilisé l'outil de requête (icône de la loupe "Exécuter des requêtes SQL abritairs") ou vous pouvez utiliser des plugins-> PSQL Console

Remarque

Si des extensions sont installées, elles seront supprimées lorsque vous supprimerez le schéma, vous devez donc prendre note de ce que vous devez installer, puis exécuter des instructions si nécessaire. Par exemple

CREATE EXTENSION postgis;

Utilisateur
la source
7
Confirmé. La solution à deux lignes fonctionnait ( dropalors create) sur PostgreSQL 9.1. Après la mise à niveau vers 9.3, les deux supplémentaires grantsont nécessaires.
Jinghao Shi
4
Une autre confirmation: en utilisant Django, j'ai eu la même erreur; J'ai dû exécuter ces subventions avant que django puisse interagir avec la base de données.
rjh
2
Cela a fonctionné parfaitement, sauf que j'avais également besoin de réinstaller certaines extensions: CREATE EXTENSION IF NOT EXISTS hstore; CRÉER UNE EXTENSION S'IL N'EXISTE PAS pgcrypto;
shacker
173

Vous pouvez supprimer toutes les tables avec

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

OMI, c'est mieux que drop schema public, car vous n'avez pas besoin de recréer le schemaet de restaurer toutes les subventions.

Bonus supplémentaire qui ne nécessite pas de langage de script externe, ni de copier-coller du SQL généré vers l'interpréteur.

Piotr Findeisen
la source
4
Merci d'avoir posté ça! Je n'ai pas pu utiliser cette drop schemaastuce car l'utilisateur n'était pas propriétaire du schéma, seulement des tables. Celui-ci a bien fonctionné :)
vdboor
Très propre et spécifique ... excellente solution, et devrait également être acceptée - vous pouvez même ajouter à la clause where pour limiter les tables que vous souhaitez conserver, comme dans celles requises par des extensions telles que PostGIS ...
DPSSpatial
Je suggère de changer cette ligne EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; avec ceci: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger
@tyger Pourquoi? Cela ressemble à une complication inutile pour moi. Y a-t- il une possibilité d'injection (et est-ce vraiment une solution s'il y en a)? [Je ne sais pas si Postgres est assez stupide pour permettre aux noms de table de rendre cela possible] Si c'est le cas, vous devriez vraiment changer votre commentaire en une modification dans la réponse (en expliquant pourquoi dans les commentaires de modification).
Auspex
@Auspex Heh, c'était un problème avec l'ancienne variante quand je faisais ça. Je ne me souviens pas pour le moment ...
Tyger
127

Si tout ce que vous souhaitez supprimer appartient au même utilisateur, vous pouvez utiliser:

drop owned by the_user;

Cela supprimera tout ce que l'utilisateur possède.

Cela inclut les vues matérialisées, les vues, les séquences, les déclencheurs, les schémas, les fonctions, les types, les agrégats, les opérateurs, les domaines, etc. (donc, vraiment: tout ) qui the_userappartient (= créé).

Vous devez remplacer the_userpar le nom d'utilisateur réel, actuellement il n'y a pas d'option pour tout supprimer pour "l'utilisateur actuel". La prochaine version 9.5 aura l'option drop owned by current_user.

Plus de détails dans le manuel: http://www.postgresql.org/docs/current/static/sql-drop-OWN.html

un cheval sans nom
la source
2
Cela a supprimé tous les schémas appartenant à l'utilisateur (ce que je ne voulais pas faire).
Peter L
4
@PeterL: qui est clairement documenté dans le manuel, mais j'ai modifié mon article pour qu'il soit clair que "tout" signifie vraiment tout
a_horse_with_no_name
J'utiliserais drop appartenant à current_user; De cette façon, vous n'avez même pas à vous soucier de taper le nom d'utilisateur correct.
JavaGeek
2
En fait, une très bonne solution pour moi. Ma base de données et mon publicschéma appartiennent à postgres, mais tout le reste appartient à un utilisateur spécifique, donc supprimer tout ce qui appartient à cet utilisateur efface la base de données à l' exception du schéma.
Auspex
Notez que la documentation dit qu'elle révoquera les privilèges mais si vous l'exécutez en tant qu'utilisateur normal, cela ne peut pas, donc elle supprime simplement les tables et autres, ce qui est exactement ce que je veux. Agréable!
ChetPrickles
76

Comme par Pablo ci-dessus, pour simplement passer d'un schéma spécifique, par rapport à la casse:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';
LenW
la source
J'ai utilisé cela, qui a fonctionné pour moi. Je suppose que la where schemaname='public'pièce est importante?
ibic
1
@ibic Si vous omettez, vous pouvez également essayer de supprimer toutes les tables internes postgres, ce qui n'est probablement pas ce que vous voulez.
tourbillon
49
drop schema public cascade;

devrait faire l'affaire.

Joe Van Dyk
la source
10
Notez que cela supprimera également toutes les fonctions, vues, etc. définies dans le schéma public.
Joe Van Dyk
6
vous devrez également recréer ensuite pour ajouter les tables avec CREATE SCHEMA public;. Voir également stackoverflow.com/a/14286370 pour plus d'informations
mikermcneil
29

Après Pablo et LenW, voici un one-liner qui fait tout à la fois la préparation et l'exécution:

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

NB: définissez ou remplacez $PGUSERet $PGDBavec les valeurs que vous souhaitez

Tim Diggins
la source
22

Si le langage procédural PL / PGSQL est installé, vous pouvez utiliser ce qui suit pour tout supprimer sans script externe 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();

Plutôt que de taper ceci à l'invite "psql", je vous suggère de le copier dans un fichier, puis de passer le fichier en entrée à psql en utilisant les options "--file" ou "-f":

psql -f clean_all_pg.sql

Crédit à qui le crédit est dû: j'ai écrit la fonction, mais je pense que les requêtes (ou la première au moins) sont venues de quelqu'un sur l'une des listes de diffusion pgsql il y a des années. Je ne me souviens pas exactement quand ni lequel.

Mark Lawrence
la source
20

Si vous souhaitez de toute façon supprimer toutes les tables, vous pouvez vous passer de subtilités telles que CASCADE en mettant toutes les tables dans une seule instruction. Cela rend également l'exécution plus rapide.

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

L'exécuter directement:

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

Remplacez TRUNCATEpar DROPle cas échéant.

Endre Both
la source
1
lorsque vous n'opérez pas sur le publicschéma, n'oubliez pas d'inclure le nom du schéma dans l'expression: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')au lieu de simplement passer les noms de table.
B12Toaster
15

J'ai légèrement modifié la réponse de Pablo pour la commodité d'avoir les commandes SQL générées renvoyées en une seule chaîne:

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

Utilisez ce script dans 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
la source
Ce sql a échoué pour moi. J'ai utilisé SELECT concat ('drop table', tablename, 'cascade;') AS drop_table_sql FROM pg_tables WHERE schemaname = 'public'
Keith John Hutchison
1
Ça a dû être quelque chose que j'ai mal fait, Luca. Je viens de l'essayer à nouveau et cela a fonctionné.
Keith John Hutchison
11

Juste au cas où ... Script Python simple qui nettoie la base de données 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]

Assurez-vous qu'après l'avoir copié, l'indentation est correcte car Python s'appuie dessus.

Piotr Kochański
la source
1
les oeuvres bordent un charme. J'ai choisi ceci parce que j'aimais coder en dur les informations de connexion à la base de données - la dernière chose que je veux faire est de frapper la mauvaise base de données! et, aussi, ma liste de tables est une cible mouvante.
JL Peyret
9

Vous pouvez utiliser la fonction string_agg pour créer une liste séparée par des virgules, parfaite pour DROP TABLE. À partir d'un 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"
Jamie
la source
devrait être #! / bin / sh
Bonne personne
9

C'est une question vraiment intéressante, et vous y arriverez de plusieurs manières. J'espère que cela vous sera utile.

  1. En supprimant et en recréant le schéma actuel

Ici, en général, nous avons un publicschéma par défaut. Donc, je l'utilise comme instance.

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

Si vous utilisez PostgreSQL 9.3 ou supérieur, vous devrez peut-être également restaurer les autorisations par défaut.

Avantages:

Cela nettoiera tout un schéma et le recréera comme un nouveau.

Les inconvénients:

Vous perdrez d' autres entités aussi comme Functions, Views, Materialized views, etc.

  1. En utilisant l'extraction de tous les noms de pg_tablestable de la table.

PostgreSQL stocke toutes les tables sur sa table d'enregistrement nommée pg_table.

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

Comme vous pouvez le voir, en utilisant la sous-requête, nous pouvons supprimer l'intégralité des tables du schéma.

Avantages:

Lorsque les autres entités de données sont importantes et que vous souhaitez simplement supprimer uniquement les tables du schéma, cette approche vous sera vraiment utile.

Mayur
la source
1
juste ce dont j'avais besoin, merci @Mayur
mikaelovi Il y a
8

Si vous souhaitez supprimer des données (pas supprimer la table):

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

Ou si vous voulez déposer une table, vous pouvez utiliser ce 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>';
pooya
la source
8

Remarque: ma réponse consiste à supprimer réellement les tables et autres objets de base de données; pour la suppression de toutes les données dans les tableaux, à savoir tronquer toutes les tables , Endre deux a fourni une déclaration (exécution directe) Similairement bien exécuté un mois plus tard.

Pour les cas où vous ne pouvez pas simplement DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;ou quelque chose comme ça, voici un script SQL autonome que j'ai écrit, qui est sûr pour les transactions (c'est-à-dire que vous pouvez le mettre entre BEGIN;et soit le ROLLBACK;tester simplement, soit COMMIT;faire l'acte) et nettoie «tous» les objets de la base de données… enfin, tous ceux utilisés dans la base de données que notre application utilise ou je pourrais raisonnablement ajouter, ce qui est:

  • déclencheurs sur les tables
  • les contraintes sur les tables (FK, PK, CHECK,UNIQUE )
  • indicēs
  • VIEWs (normal ou matérialisé)
  • les tables
  • séquences
  • routines (fonctions agrégées, fonctions, procédures)
  • tous les schémas nōn par défaut (c'est-à-dire non publicou internes à la base de données) «que nous» possédons: le script est utile lorsqu'il est exécuté en tant que «pas un superutilisateur de base de données»; un superutilisateur peut tout laisser tomber schémas (les plus importants sont cependant explicitement exclus)
  • extensions (fournies par l'utilisateur, mais je les laisse normalement délibérément)

Non abandonnés sont (certains délibérés; certains uniquement parce que je n'avais aucun exemple dans notre DB):

  • le public schéma (par exemple pour les éléments fournis par l'extension)
  • des classements et d'autres trucs locaux
  • déclencheurs d'événements
  • recherche de texte,… (voir ici pour d'autres choses que j'aurais pu manquer)
  • rôles ou autres paramètres de sécurité
  • types composites
  • tables de toast
  • FDW et tables étrangères

Ceci est vraiment utile dans les cas où le vidage que vous souhaitez restaurer est d'une version de schéma de base de données différente (par exemple avec Debiandbconfig-common , Flyway ou Liquibase / DB-Manul) que la base de données dans laquelle vous souhaitez le restaurer.

J'ai également une version qui supprime «tout sauf deux tables et ce qui leur appartient» (une séquence, testée manuellement, désolé, je sais, ennuyeuse) au cas où quelqu'un serait intéressé; le diff est petit. Contactez-moi ou consultez ce repo si vous intéressé.

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

Testé, sauf ajouts ultérieurs ( extensionscontribution de Clément Prévost ), sur PostgreSQL 9.6 ( jessie-backports). Suppression d'agrégats testée sur 9.6 et 12.2, retrait de procédure également testé sur 12.2. Les corrections de bugs et autres améliorations sont les bienvenues!

mirabilos
la source
Il y a des erreurs dans le script ci-dessus car il ne fait pas de distinction entre les fonctions et les procédures: DROP FUNCTIONéchoue pour une procédure, et vice versa. J'ai modifié la section de fonction à ceci: AND pp.prokind ='f' -- FunctionouAND pp.prokind ='p' -- Procedure
BogeyMan
1
@BogeyMan Ce n'est pas une erreur, l'omission des fonctions d'agrégation a été documentée et le script a été documenté pour être testé sur 9.6 uniquement. Mais j'ai pris votre commentaire à cœur et je l'ai adapté pour gérer les agrégats ( proisagg) sur ≤ 10.x et les agrégats et les procédures ( prokind) sur ≥ 11 (vérifié dynamiquement) et j'ai testé les deux ☻ merci pour l'astuce.
mirabilos
6

Vous devez supprimer des tableaux et des séquences, voici ce qui a fonctionné pour moi

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

avant d'exécuter la commande que vous pourriez avoir besoin de Sudo / su à l' postgresutilisateur ou (détails connexion à l'exportation PGHOST, PGPORT, PGUSERet PGPASSWORD) puisexport PGDATABASE=yourdatabase

Muayyad Alsadi
la source
5

Rake task for Rails for destroy all tables in current database

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
l'enseignant
la source
1
Il pourrait être plus simple / plus sûr de dire AND table_schema = 'public' plutôt que PAS DANS cette liste.
Steve
Pour une raison quelconque, mon schéma a été créé avec des données remplies. Ce râteau fonctionne. Alors après rake db:create, je l'exécute. Vous pouvez faire l'astuce de Steve et supprimer le code table_name = et changer ", "pour ","et #{ tables }fo#{tables}
Washington Botelho
5

Les étapes suivantes peuvent être utiles (pour les utilisateurs de Linux):

  1. Entrez d'abord l' postgresinvite de commande en suivant la commande:

    sudo -u postgres psql
  2. Entrez la base de données par cette commande (mon nom de base de données est:) maoss:

    \c maoss
  3. Entrez maintenant la commande pour supprimer toutes les tables:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
FaridLU
la source
1
suivi les étapes sur mon ubuntu 19.04, cela a fonctionné parfaitement!
Alexandru-Mihai Manolescu
1
@FaridLU Beaucoup aidé, merci!
Justin Wood
4

J'ai amélioré la méthode bash de jamie en prenant soin des vues car la sienne ne respecte que le type de table "table de base" qui est la valeur par défaut.

le code bash suivant supprime d'abord les vues, puis tout le reste

#!/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
la source
Grand script ... juste utilisé et a fonctionné comme un charme. J'ai également ajouté une ligne pour les séquences: 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

dans un fichier batch 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
)
Lewis
la source
2

bien, puisque j'aime travailler depuis la ligne de commande ...

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

-c '\dt' invoquera la commande list tables.

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

cut -d ' ' -f 4 maintenant, dirigez sa sortie pour saisir le 4ème champ (lorsque vous utilisez l'espace comme séparateur), qui est la table.

sedest ensuite utilisé pour préfixer a drop tableet suffixer le ;séparateur de commandes.

| egrep '_d_'- Ajoutez-en grepplus et vous pouvez être plus sélectif sur les tables que vous supprimez.

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

Remarque: tel qu'écrit, cela générera de fausses lignes pour la \dtsortie des commandes des en-têtes de colonne et le total des lignes à la fin. J'évite cela en applaudissant, mais vous pouvez utiliser headet tail.

JL Peyret
la source
2

Le moyen le plus simple consiste à supprimer le schéma public comme d'autres l'ont suggéré dans les réponses précédentes. Cependant, ce n'est PAS un bon moyen. Vous ne savez jamais ce qui a été fait au schéma public qui a depuis été oublié et n'a pas été documenté. Vous ne savez pas non plus si cela fonctionnera de la même manière à l'avenir. Dans la version 9, cela aurait été bien, mais dans la version 10, tous vos utilisateurs perdraient l'accès au schéma et ils devraient à nouveau y accéder, sinon votre application se briserait. Je n'ai pas vérifié la V11, mais le fait est que vous ne savez jamais ce qui se cassera lorsque vous passez d'une machine à l'autre, d'un site à l'autre ou d'une version à une autre. Cela ne peut pas non plus être fait si vous êtes un utilisateur qui a accès à la base de données, mais pas au schéma.

Si vous devez le faire par programme, les autres réponses ci-dessus couvrent cela, mais une chose que les réponses ci-dessus ne prennent pas en compte est de demander à Postgres de faire le travail pour vous. Si vous utilisez pg_dump avec l'option -c comme ci-dessous:

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

Cela créera un script de restauration de base de données avec des instructions sql qui supprimera toutes les tables.

Si le seul but en posant la question était de supprimer les tables avant la restauration, votre restauration fera le travail pour vous.

Cependant, si vous en avez besoin pour autre chose, vous pouvez simplement copier les instructions drop du script sql.

RichardP
la source