¿Cómo puedo descartar todas las tablas en una base de datos PostgreSQL?

1047

¿Cómo puedo colocar todas las tablas en PostgreSQL, trabajando desde la línea de comandos?

Yo no quiero caer la propia base de datos, a todas las tablas y todos los datos en ellos.

AP257
fuente
3
¿De qué línea de comando estás hablando? Por lo que sabemos, está buscando una implementación de Windows PowerShell.
Greg Smith
44
Lo siento. Trabajando en Unix, después de escribir 'psql' en la línea de comandos, entonces el entorno de la línea de comandos psql en sí.
AP257
101
ESQUEMA DE CAÍDA CASCADA pública; - estremecimiento
wildplasser
20
@ 0fnt tendrá que hacer 'CREAR ESQUEMA público;' agregar nuevas tablas nuevamente (descubierto de la manera difícil)
nym
44
Por cierto, cuando caes public, pierdes las extensiones instaladas.
sudo

Respuestas:

1382

Si todas sus tablas están en un solo esquema, este enfoque podría funcionar (el código siguiente supone que el nombre de su esquema es public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Si está utilizando PostgreSQL 9.3 o superior, es posible que también deba restaurar las concesiones predeterminadas.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Derek Slife
fuente
105
Tenga en cuenta que esto también eliminará todas las funciones, vistas, etc. definidas en el esquema público.
Brad Koch
55
Tenga en cuenta que esto no eliminará las tablas del sistema (tales como los que comienzan con pg_) ya que están en un esquema diferente, pg_catalog.
congusbongus
36
Esto creará el esquema con OWNER configurado para el usuario con el que inició sesión en psql. Esto entrará en conflicto con las aplicaciones que inician sesión como un usuario diferente. En ese caso, también debe ejecutar "ALTER SCHEMA public OWNER to postgres;" (o para cualquier usuario que use su aplicación para crear tablas)
mgojohn
13
Sacando esto de otra respuesta que probablemente desee tener GRANT ALL ON SCHEMA public TO public;después de la creación.
Federico
1
@Federico ¿Por qué querrías GRANT ALLdespués de crear?
425nesp
410

Puede escribir una consulta para generar un script SQL como este:

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

O:

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

En caso de que algunas tablas se eliminen automáticamente debido a la opción de cascada en una oración anterior.

Además, como se indica en los comentarios, es posible que desee filtrar las tablas que desea colocar por nombre de esquema:

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

Y luego ejecútalo.

Glorious COPY + PASTE también funcionará.

Pablo Santa Cruz
fuente
15
Creo que quisiste decir: puedes escribir una consulta como esta ... ... y luego ejecutar el resultado de la consulta
Vinko Vrsalovic
55
seleccione 'soltar tabla si existe "' || nombre de tabla || '" cascada;' de pg_tables; se asegurará de que las tablas con mayúsculas también se caigan correctamente.
Ivo van der Wijk
12
la cláusula "where schemaname = 'public'" que LenW agregó en su respuesta puede ser muy útil para reducir el alcance de eliminación solo a la base de datos que usted administró y no a las del sistema
Guillaume Gendre
8
@jwg: también, porque a veces no tienes permiso para hacerlo drop schema public cascade;, pero casi siempre tienes los permisos para soltar tablas.
Berkes
2
Versión para esquemas no públicos: seleccione 'soltar tabla si existe "' || schemaname || '". "' || tablename || '" cascade;' de pg_tables donde schemaname = 'user_data';
Ludwig
292

La respuesta más aceptada a partir de este escrito (enero de 2014) es:

drop schema public cascade;
create schema public;

Esto funciona, sin embargo, si su intención es restaurar el esquema público a su estado virgen, esto no cumple completamente la tarea. En pgAdmin III para PostgreSQL 9.3.1, si hace clic en el esquema "público" creado de esta manera y busca en el "panel SQL", verá lo siguiente:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Sin embargo, por el contrario, una nueva base de datos tendrá lo siguiente:

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

Para mí, usar un marco web de Python que crea tablas de base de datos (web2py), usando los problemas anteriores:

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

Entonces, en mi opinión, la respuesta correcta es:

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

También tenga en cuenta que para emitir estos comandos en pgAdmin III, utilicé la herramienta de consulta (icono de lupa "Ejecutar consultas SQL abritrarias") o podría usar Plugins-> Consola PSQL

Nota

Si tiene alguna extensión instalada, se eliminarán cuando elimine el esquema, por lo que debe tomar nota de lo que necesita instalar y luego ejecutar las declaraciones según sea necesario. P.ej

CREATE EXTENSION postgis;

Usuario
fuente
77
Confirmado. La solución de dos líneas ( dropentonces create) solía funcionar en PostgreSQL 9.1. Después de actualizar a 9.3, los dos adicionales grantson necesarios.
Jinghao Shi
44
Una confirmación más: usando Django, obtuve el mismo error; Necesitaba ejecutar esas subvenciones antes de que django pudiera interactuar con la base de datos.
rjh
2
Esto funcionó perfectamente, excepto que también necesitaba reinstalar algunas extensiones: CREAR EXTENSIÓN SI NO EXISTE hstore; CREAR EXTENSIÓN SI NO EXISTE pgcrypto;
Shacker
173

Puede soltar todas las tablas 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 $$;

OMI, esto es mejor que drop schema public, porque no es necesario volver a crear schemay restaurar todas las subvenciones.

Una ventaja adicional de que esto no requiere lenguaje de secuencias de comandos externo, ni copiar y pegar el SQL generado al intérprete.

Piotr Findeisen
fuente
44
¡Gracias por publicar esto! No pude usar el drop schematruco ya que el usuario no era dueño del esquema, solo de las tablas. Aunque funcionó :)
vdboor
Muy limpio y específico ... una gran solución, y también debe ser aceptada, incluso puede agregar a la cláusula where para limitar las tablas que desea mantener, como las que necesitan las extensiones como PostGIS ...
DPSSpatial
Sugeriría cambiar esa línea EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; con esto: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger
@tyger ¿Por qué? Me parece una complicación innecesaria. ¿ Existe alguna posibilidad de inyección (y esto realmente soluciona una si la hay)? [No sé si Postgres es tan tonto como para permitir que los nombres de las tablas lo hagan posible] Si es así, realmente debería cambiar su comentario a una edición en la respuesta (explicando por qué en los comentarios de edición).
Auspex
@Auspex Heh, fue un problema con la variante anterior cuando estaba haciendo eso. No puedo recordar en este momento ...
tyger
127

Si todo lo que desea soltar es propiedad del mismo usuario, puede usar:

drop owned by the_user;

Esto eliminará todo lo que posee el usuario.

Eso incluye vistas materializadas, vistas, secuencias, disparadores, esquemas, funciones, tipos, agregados, operadores, dominios, etc. (así, realmente: todo ) que the_userposee (= creado).

Debe reemplazarlo the_usercon el nombre de usuario real, actualmente no hay opción para soltar todo para "el usuario actual". La próxima versión 9.5 tendrá la opción drop owned by current_user.

Más detalles en el manual: http://www.postgresql.org/docs/current/static/sql-drop-owned.html

un caballo sin nombre
fuente
2
Esto eliminó todos los esquemas propiedad del usuario (que no quería hacer).
Peter L
44
@PeterL: que está claramente documentado en el manual, pero edité mi publicación para dejar en claro que "todo" realmente significa todo
a_horse_with_no_name
Usaría drop propiedad de current_user; De esta manera, ni siquiera tiene que preocuparse por escribir el nombre de usuario correcto.
JavaGeek
2
En realidad, una muy buena solución para mí. Mi base de datos y mi publicesquema son propiedad postgres, pero todo lo demás es propiedad de un usuario específico, por lo que descartar todo lo que posee ese usuario borra la base de datos, excepto el esquema.
Auspex
Tenga en cuenta que la documentación dice que revocará los privilegios, pero si ejecuta esto como un usuario normal, no puede, por lo que simplemente elimina las tablas y similares, que es exactamente lo que quiero. ¡Agradable!
ChetPrickles
76

Según Pablo arriba, para caer de un esquema específico, con respecto al caso:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';
LenW
fuente
Usé esto, que funcionó para mí. ¿Asumo que la where schemaname='public'parte es significativa?
Ibic
1
@ibic Si deja de lado, puede intentar eliminar también todas las tablas internas de postgres, lo que probablemente no sea lo que desea.
whirlwin
49
drop schema public cascade;

debería hacer el truco.

Joe Van Dyk
fuente
10
Tenga en cuenta que esto también eliminará todas las funciones, vistas, etc. definidas en el esquema público.
Joe Van Dyk
66
También tendrá que volver a crear después para volver a agregar las tablas CREATE SCHEMA public;. También consulte stackoverflow.com/a/14286370 para obtener más información
mikermcneil
29

Siguiendo a Pablo y LenW, aquí hay una frase que lo prepara todo y luego lo ejecuta:

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

NB: establezca o reemplace $PGUSERy $PGDBcon los valores que desee

Tim Diggins
fuente
22

Si tiene instalado el lenguaje de procedimiento PL / PGSQL, puede usar lo siguiente para eliminar todo sin un script externo de 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();

En lugar de escribir esto en el indicador "psql", le sugiero que lo copie en un archivo y luego pase el archivo como entrada a psql usando las opciones "--file" o "-f":

psql -f clean_all_pg.sql

Crédito donde es debido: escribí la función, pero creo que las consultas (o al menos la primera) provienen de alguien en una de las listas de correo pgsql hace años. No recuerdo exactamente cuándo o cuál.

Mark Lawrence
fuente
20

Si de todos modos desea destruir todas las tablas, puede prescindir de detalles como CASCADE colocando todas las tablas en una sola declaración. Esto también hace que la ejecución sea más rápida.

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

Ejecutándolo directamente:

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

Reemplace TRUNCATEcon DROPsegún corresponda.

Endre Both
fuente
1
cuando no esté operando en el publicesquema, no olvide incluir el nombre del esquema en la expresión: en string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')lugar de simplemente pasar los nombres de las tablas.
B12Toaster
15

Modifiqué ligeramente la respuesta de Pablo para la conveniencia de que los comandos SQL generados se devuelvan como una sola cadena:

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

Use este script en 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
fuente
Ese sql falló para mí. Usé SELECT concat ('drop table', tablename, 'cascade;') AS drop_table_sql FROM pg_tables WHERE schemaname = 'public'
Keith John Hutchison
1
Debe haber sido algo que hice mal, Luca. Lo intenté de nuevo y funcionó.
Keith John Hutchison
11

Por si acaso ... Script Python simple que limpia la base de datos 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]

Asegúrese de que después de copiarlo, la sangría sea correcta ya que Python se basa en ella.

Piotr Kochański
fuente
1
La línea de obras es un encanto. Elegí esto porque me gustaba codificar la información de conexión de db. ¡Lo último que quiero hacer es presionar el db incorrecto! y, además, mi lista de tablas es un objetivo móvil.
JL Peyret
9

Puede usar la función string_agg para hacer una lista separada por comas, perfecta para DROP TABLE. De 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
fuente
debería ser #! / bin / sh
Good Person
9

Esta es una pregunta realmente interesante, y la harás de varias maneras. Espero que esto te sea útil.

  1. Al soltar y recrear el esquema actual

Aquí, en general, tenemos un publicesquema por defecto. Entonces, lo estoy usando como una instancia.

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

Si está utilizando PostgreSQL 9.3 o superior, es posible que también deba restaurar las concesiones predeterminadas.

Pros:

Esto limpiará un esquema completo y lo volverá a crear como uno nuevo.

Contras:

Si no se pierden otras entidades también, como Functions, Views, Materialized views, etc.

  1. Al utilizar la obtención de todos los nombres de pg_tablestabla de la tabla.

PostgreSQL almacena todas las tablas en su tabla de registro denominada pg_table.

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

Como puede ver, mediante el uso de subconsultas, podemos eliminar todas las tablas del esquema.

Pros:

Cuando las otras entidades de datos son importantes y solo desea eliminar solo las tablas del esquema, este enfoque será realmente útil para usted.

Mayur
fuente
justo lo que necesitaba, gracias @Mayur
mikaelovi hace
8

Si desea eliminar datos (no eliminar tabla):

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

O si desea colocar la tabla puede usar este 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
fuente
8

Nota: mi respuesta se trata de eliminar realmente las tablas y otros objetos de la base de datos; para eliminar todos los datos en las tablas, es decir, truncar todas las tablas , Endre Both ha proporcionado una declaración similarmente bien ejecutada (ejecución directa) un mes después.

Para los casos en los que no puede simplemente DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;o algo así, aquí hay un script SQL independiente que escribí, que es seguro para las transacciones (es decir, puede ponerlo entre BEGIN;y ROLLBACK;para probarlo o COMMIT;hacer el acto) y limpia "todos" los objetos de la base de datos ... bueno, todos los que se usan en la base de datos que usa nuestra aplicación o podría agregar con sensatez, que es:

  • disparadores en las mesas
  • restricciones en las tablas (FK, PK, CHECK, UNIQUE)
  • índices
  • VIEWs (normal o materializado)
  • mesas
  • secuencias
  • rutinas (funciones agregadas, funciones, procedimientos)
  • todos publiclos esquemas no predeterminados (es decir, no o internos de la base de datos) que "nosotros" poseemos: el script es útil cuando se ejecuta como "no un superusuario de base de datos"; un superusuario puede descartar todos los esquemas (sin embargo, los realmente importantes aún se excluyen explícitamente)
  • extensiones (aportadas por el usuario pero normalmente las dejo deliberadamente)

No se descartan (algunos deliberados; otros solo porque no tenía ningún ejemplo en nuestra base de datos):

  • el publicesquema (p. ej. para cosas proporcionadas por la extensión en ellos)
  • intercalaciones y otras cosas locales
  • disparadores de eventos
  • cosas de búsqueda de texto, ... (vea aquí para otras cosas que podría haber perdido)
  • roles u otras configuraciones de seguridad
  • tipos compuestos
  • mesas tostadas
  • FDW y tablas extranjeras

Esto es realmente útil para los casos en que el volcado que desea restaurar es de una versión de esquema de base de datos diferente (por ejemplo, con Debian dbconfig-common, Flyway o Liquibase / DB-Manul) que la base de datos en la que desea restaurarlo.

También tengo una versión que elimina "todo excepto dos tablas y lo que les pertenece" (una secuencia, probada manualmente, lo siento, lo sé, aburrida) en caso de que alguien esté interesado; La diferencia es pequeña. Contáctame o consulta este repositorio si estás interesado.

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

Probado, excepto adiciones posteriores ( extensionscontribuido por Clément Prévost ), en PostgreSQL 9.6 ( jessie-backports). Eliminación agregada probada en 9.6 y 12.2, eliminación de procedimiento probada también en 12.2. ¡Correcciones de errores y mejoras adicionales son bienvenidas!

mirabilos
fuente
Hay errores en el script anterior, ya que no distingue entre funciones y procedimientos: DROP FUNCTIONfalla para un procedimiento y viceversa. AND pp.prokind ='f' -- FunctionAND pp.prokind ='p' -- Procedure
Modifiqué
1
@BogeyMan Eso no es un error, la omisión de funciones agregadas se documentó y el script se documentó para probarse solo en 9.6. Pero tomé en serio su comentario y lo adapté para manejar agregados ( proisagg) en ≤ 10.x y agregados y procedimientos ( prokind) en ≥ 11 (verificado dinámicamente) y probé ambos ☻ gracias por la pista.
mirabilos
6

Necesitas soltar tablas y secuencias, esto es lo que funcionó para mí

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

antes de ejecutar el comando puede que tenga que sudo / Do a los postgresusuarios o (conexión de exportación Información PGHOST, PGPORT, PGUSERy PGPASSWORD) y luegoexport PGDATABASE=yourdatabase

Muayyad Alsadi
fuente
5

Rastrillar tarea para Rails para destruir todas las tablas en la base de datos actual

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
el maestro
fuente
1
Podría ser más simple / seguro decir AND table_schema = 'public' en lugar de NOT IN that list.
Steve
Por alguna razón, mi esquema se creó con datos poblados. Este rastrillo funciona. Entonces, después de hacerlo rake db:create, lo ejecuto. Usted puede hacer la punta Steve y eliminar el código table_name = y el cambio ", "de ","y #{ tables }fo#{tables}
Washington Botelho
5

Los siguientes pasos pueden ser útiles (para usuarios de Linux):

  1. Al principio ingrese el postgressímbolo del sistema mediante el siguiente comando:

    sudo -u postgres psql
  2. Ingrese la base de datos con este comando (el nombre de mi base de datos es:) maoss:

    \c maoss
  3. Ahora ingrese el comando para descartar todas las tablas:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
FaridLU
fuente
1
Seguí los pasos en mi ubuntu 19.04, ¡funcionó a la perfección!
Alexandru-Mihai Manolescu
1
@FaridLU Ayudó mucho, ¡gracias!
Justin Wood
4

Mejoré el método bash de jamie cuidando las vistas porque solo respeta el tipo de tabla "tabla base", que es el valor predeterminado.

el siguiente código bash elimina las vistas primero y luego todo el 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"
martinseener
fuente
Gran guión ... simplemente lo usé y funcionó a las mil maravillas. También agregué una línea para secuencias: SECUENCIAS =psql -d $PGDB -t --command "SELECT string_agg(sequence_name, ',') FROM information_schema.sequences WHERE sequence_schema='public' AND sequence_catalog='$PGDB'"
raminr
4

en un archivo por lotes de 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
)
Luis
fuente
2

bueno, ya que me gusta trabajar desde la línea de comando ...

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

-c '\dt' invocará el comando list tables.

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

cut -d ' ' -f 4 ahora, canalice su salida para tomar el cuarto campo (cuando use el espacio como separador), que es la tabla.

sedluego se usa para prefijar ay drop tablesufijo el ;separador de comandos.

| egrep '_d_'- Conéctelo un greppoco más y puede ser más selectivo sobre las tablas que suelta.

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

Nota: como está escrito, esto generará filas falsas para la \dtsalida de comandos de encabezados de columna y filas totales al final. Lo evito haciendo grepping, pero podrías usar heady tail.

JL Peyret
fuente
2

La forma más fácil es eliminar el esquema público como otros han sugerido en respuestas anteriores. Sin embargo, esta NO es una buena manera. Nunca se sabe lo que se ha hecho al esquema público que desde entonces se ha olvidado y no se documentó. Tampoco sabe si esto funcionará igual en el futuro. En V9, hubiera estado bien, pero en V10 todos sus usuarios perderían el acceso al esquema, y ​​se les debe otorgar acceso nuevamente, de lo contrario su aplicación se romperá. No he comprobado V11, pero el punto es que nunca se sabe qué se romperá a medida que se mueva de máquina a máquina, de sitio a sitio o de versión a versión. Tampoco se puede hacer si es un usuario que tiene acceso a la base de datos, pero no al esquema.

Si necesita hacer esto mediante programación, otras respuestas anteriores cubren esto, pero una cosa que las respuestas anteriores no consideran es hacer que Postgres haga el trabajo por usted. Si usa pg_dump con la opción -c como se muestra a continuación:

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

Eso creará un script de restauración de base de datos con sentencias sql que eliminará todas las tablas.

Si el único propósito al hacer la pregunta era eliminar las tablas antes de restaurar, entonces su restauración hará el trabajo por usted.

Sin embargo, si lo necesita para otra cosa, simplemente puede copiar las declaraciones de caída del script sql.

RichardP
fuente