Como posso soltar todas as tabelas em um banco de dados PostgreSQL?

1047

Como posso eliminar todas as tabelas no PostgreSQL, trabalhando na linha de comando?

Eu não quero largar o próprio banco de dados, apenas a todas as tabelas e todos os dados em si.

AP257
fonte
3
De que linha de comando você está falando? Pelo que sabemos, você está procurando uma implementação do Windows PowerShell.
Greg Smith
4
Desculpa. Trabalhando no Unix, depois de digitar 'psql' na linha de comando - o próprio ambiente de linha de comando psql.
AP257 25/07/10
101
ESQUEMA DE GOTA CASCADE público; - shudder
wildplasser
20
@ 0fnt você terá que fazer 'CREATE SCHEMA public;' para adicionar novas tabelas novamente (descobriu da maneira mais difícil)
nym
4
BTW, quando você solta public, você perde todas as extensões instaladas.
sudo

Respostas:

1380

Se todas as suas tabelas estiverem em um único esquema, essa abordagem poderá funcionar (o código abaixo assume que o nome do seu esquema é public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Se você estiver usando o PostgreSQL 9.3 ou superior, também poderá ser necessário restaurar as concessões padrão.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Derek Slife
fonte
105
Observe que isso também excluirá todas as funções, visualizações etc. definidas no esquema público.
Brad Koch
5
Observe que isso não removerá as tabelas do sistema (como aquelas que começam com pg_), pois estão em um esquema diferente pg_catalog.
Congusbongus
36
Isso criará o esquema com OWNER definido para o usuário no qual você está conectado ao psql. Isso entrará em conflito com os aplicativos que efetuam login como um usuário diferente. Nesse caso, você também precisa executar "ALTER SCHEMA public OWNER to postgres;" (ou para qualquer usuário que usa seu aplicativo para criar tabelas)
mgojohn
13
Trazendo isso a partir de outra resposta, você provavelmente deseja ter um GRANT ALL ON SCHEMA public TO public;após a criação.
Federico
1
@Federico Por que você desejaria GRANT ALLapós a criação?
425nesp
410

Você pode escrever uma consulta para gerar um script SQL como este:

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

Ou:

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

Caso algumas tabelas sejam eliminadas automaticamente devido à opção em cascata em uma frase anterior.

Além disso, conforme indicado nos comentários, convém filtrar as tabelas que deseja excluir pelo nome do esquema:

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

E depois execute.

Glorioso COPY + PASTE também funcionará.

Pablo Santa Cruz
fonte
15
Eu acho que você quis dizer: Você pode escrever uma consulta como esta ... ... E, em seguida, executar a saída da consulta
Vinko Vrsalovic
5
selecione 'soltar tabela se existir "' || tablename || '" cascade;' de pg_tables; garantirá que as tabelas com maiúsculas também sejam descartadas corretamente.
Ivo van der Wijk
12
a cláusula "onde schemaname = 'público'" que LenW adicionado em sua resposta pode ser muito útil para reduzir o âmbito da exclusão apenas o banco de dados gerenciado e não os do sistema
Guillaume Gendre
8
@jwg: também, porque às vezes você não tem permissão drop schema public cascade;, mas quase sempre tem permissão para descartar tabelas.
Berkes
2
Versão para esquemas não públicos: selecione 'soltar tabela se existir "' || schemaname || '". "' || nome da tabela || '" cascade;' de pg_tables em que schemaname = 'user_data';
ludwig
292

A resposta mais aceita até o momento em que este artigo foi escrito (janeiro de 2014) é:

drop schema public cascade;
create schema public;

Isso funciona, no entanto, se sua intenção é restaurar o esquema público para seu estado virgem, isso não realiza completamente a tarefa. No pgAdmin III para PostgreSQL 9.3.1, se você clicar no esquema "público" criado dessa maneira e procurar no "painel SQL", verá o seguinte:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

No entanto, por outro lado, um novo banco de dados terá o seguinte:

-- 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 mim, usando um framework web python que cria tabelas de banco de dados (web2py), o uso dos primeiros causou problemas:

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

Então, na minha opinião, a resposta totalmente correta é:

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

Observe também que para emitir esses comandos no pgAdmin III, usei a ferramenta Query (ícone da lupa "Executar consultas SQL abritrárias") ou você pode usar Plugins-> PSQL Console

Nota

Se você tiver alguma extensão instalada, ela será descartada quando você soltar o esquema; portanto, anote o que você precisa instalar e execute as instruções conforme necessário. Por exemplo

CREATE EXTENSION postgis;

Do utilizador
fonte
7
Confirmado. A solução de duas linhas ( dropentão create) costumava funcionar no PostgreSQL 9.1. Após a atualização para 9.3, os dois extras grantsão necessários.
Jinghao Shi 15/09/14
4
Mais uma confirmação: usando o Django, recebi o mesmo erro; Eu precisava executar essas concessões antes que o django pudesse interagir com o banco de dados.
Rjh
2
Isso funcionou perfeitamente, exceto que eu também precisei reinstalar algumas extensões: CRIAR EXTENSÃO SE NÃO EXISTIR hstore; CRIAR EXTENSÃO SE NÃO EXISTIR pgcrypto;
shacker
173

Você pode soltar todas as tabelas com

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

Para a IMO, é melhor que isso drop schema public, porque você não precisa recriar schemae restaurar todas as concessões.

Bônus adicional por não exigir linguagem de script externa nem copiar e colar o SQL gerado de volta ao intérprete.

Piotr Findeisen
fonte
4
Obrigado por postar isso! Não pude usar o drop schematruque, pois o usuário não era proprietário do esquema, apenas das tabelas. Este trabalhou embora :)
vdboor
Muito limpo e específico ... ótima solução e também deve ser aceita - você pode até adicionar a cláusula where para limitar as tabelas que deseja manter, como as necessárias para extensões como PostGIS ...
DPSSpatial
Eu sugeriria mudar essa linha EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; com este: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger
@tyger Por quê? Parece uma complicação desnecessária para mim. Existe uma possibilidade de injeção (e isso realmente corrige uma, se houver)? [Eu não sei se o Postgres é tolo o suficiente para permitir que os nomes das tabelas tornem isso possível] .
Auspex
@ Auspex Heh, houve algum problema com a variante anterior quando eu estava fazendo isso. Não consigo me lembrar agora ...
tyger 31/05/19
127

Se tudo o que você deseja soltar pertence ao mesmo usuário, você pode usar:

drop owned by the_user;

Isso descartará tudo o que o usuário possui.

Isso inclui visualizações materializadas, visualizações, sequências, gatilhos, esquemas, funções, tipos, agregados, operadores, domínios e assim por diante (então, realmente: tudo ) que the_userpossui (= criado).

Você precisa substituir the_userpelo nome de usuário real. Atualmente, não há opção de descartar tudo para "o usuário atual". A próxima versão 9.5 terá a opção drop owned by current_user.

Mais detalhes no manual: http://www.postgresql.org/docs/current/static/sql-drop-owned.html

um cavalo sem nome
fonte
2
Isso eliminou todos os esquemas de propriedade do usuário (o que eu não queria fazer).
Peter L
4
@PeterL: que é claramente documentado no manual, mas eu editei o meu post para deixar claro que "tudo" realmente significa tudo
a_horse_with_no_name
Eu usaria drop pertencente a current_user; Dessa forma, você nem precisa se preocupar em digitar o nome de usuário correto.
JavaGeek
2
Na verdade, uma solução muito boa para mim. Meu banco de dados e publicesquema são de propriedade de postgres, mas todo o resto pertence a um usuário específico; assim, eliminar tudo o que é de propriedade do usuário limpa o banco de dados, exceto o esquema.
Auspex
Observe que a documentação diz que revogará privilégios, mas se você executar isso como um usuário normal, não poderá, portanto, apenas descarta as tabelas e coisas do gênero, exatamente o que eu quero. Agradável!
ChetPrickles
76

Conforme Pablo acima, para sair apenas de um esquema específico, com relação ao caso:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';
LenW
fonte
Eu usei isso, o que funcionou para mim. Presumo que a where schemaname='public'parte seja significativa?
ibic 15/02
1
@ibic Se você deixar de fora, pode também tentar excluir todas as tabelas internas do postgres, o que provavelmente não é o que você deseja.
whirlwin
49
drop schema public cascade;

deve fazer o truque.

Joe Van Dyk
fonte
10
Observe que isso também excluirá todas as funções, visualizações etc. definidas no esquema público.
precisa
6
Além disso, você precisará recriar novamente posteriormente para adicionar as tabelas CREATE SCHEMA public;. Ver também stackoverflow.com/a/14286370 para mais informações
mikermcneil
29

Seguindo Pablo e LenW, aqui está uma lista que faz tudo ao mesmo tempo preparando e executando:

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

NB: defina ou substitua $PGUSERe $PGDBcom os valores desejados

Tim Diggins
fonte
22

Se você tiver a linguagem procedural PL / PGSQL instalada, poderá usar o seguinte para remover tudo sem um script externo 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();

Em vez de digitar isso no prompt "psql", sugiro que você o copie para um arquivo e depois passe o arquivo como entrada para o psql usando as opções "--file" ou "-f":

psql -f clean_all_pg.sql

Crédito onde o crédito é devido: eu escrevi a função, mas acho que as consultas (ou a primeira pelo menos) vieram de alguém de uma das listas de discussão do pgsql anos atrás. Não lembro exatamente quando ou qual.

Mark Lawrence
fonte
20

Se você quiser destruir todas as tabelas de qualquer maneira, poderá dispensar detalhes, como CASCADE, colocando todas as tabelas em uma única instrução. Isso também torna a execução mais rápida.

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

Executando-o diretamente:

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

Substitua TRUNCATEpor DROPconforme aplicável.

Endre Both
fonte
1
quando não estiver operando no publicesquema, não esqueça de incluir o nome do esquema na expressão: em string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')vez de simplesmente passar os nomes da tabela.
B12Toaster 22/01
15

Modifiquei ligeiramente a resposta de Pablo para a conveniência de ter os comandos SQL gerados retornados como uma única sequência:

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

Use este script no 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
fonte
Esse sql falhou para mim. Eu usei SELECT concat ('drop table', tablename, 'cascade;') AS drop_table_sql FROM pg_tables WHERE schemaname = 'public'
Keith John Hutchison
1
Deve ter sido algo que eu fiz de errado, Luca. Eu apenas tentei novamente e funcionou.
Keith John Hutchison
11

Apenas no caso ... Script Python simples que limpa o banco de dados 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]

Certifique-se de que, após copiá-lo, o recuo esteja correto, pois o Python depende dele.

Piotr Kochański
fonte
1
funciona alinhar um encanto. Eu escolhi isso porque gostava de codificar as informações da conexão db - a última coisa que quero fazer é acertar o db errado! e também minha lista de mesas é um alvo em movimento.
JL Peyret
9

Você pode usar a função string_agg para criar uma lista separada por vírgulas, perfeita para DROP TABLE. Em um 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
fonte
deve ser #! / bin / sh
Boa pessoa
8

Se você deseja excluir dados (não excluir tabela):

-- 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, se você quiser soltar a tabela, poderá 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
fonte
8

Nota: minha resposta é sobre realmente excluir as tabelas e outros objetos de banco de dados; para apagar todos os dados em tabelas, ou seja truncar todas as tabelas , Endre Ambos forneceu uma declaração similarily bem executado (execução direta), um mês depois.

Para os casos em que você não pode simplesmente DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;ou algo assim, aqui está um script SQL independente que eu escrevi, que é seguro para transações (ou seja, você pode colocá-lo entre BEGIN;e ROLLBACK;apenas para testá-lo ou COMMIT;realmente fazer a ação) e limpa “todos” os objetos do banco de dados ... bem, todos aqueles usados ​​no banco de dados que nosso aplicativo usa ou eu poderia acrescentar sensatamente, que é:

  • gatilhos nas tabelas
  • restrições de tabela (FK, PK, CHECK, UNIQUE)
  • indicações
  • VIEWs (normal ou materializado)
  • mesas
  • sequências
  • rotinas (funções agregadas, funções, procedimentos)
  • todos os esquemas não padrão (por exemplo, não publicou internos ao banco de dados) "nós" possuímos: o script é útil quando executado como "não um superusuário de banco de dados"; um superusuário pode eliminar todos os esquemas (os realmente importantes ainda são explicitamente excluídos)
  • extensões (contribuídas pelo usuário, mas normalmente as deixo deliberadamente)

Não são descartados (alguns deliberados; outros apenas porque eu não tinha exemplo em nosso banco de dados):

  • o publicesquema (por exemplo, para itens fornecidos por extensão)
  • colações e outras coisas de localidade
  • gatilhos de evento
  • pesquisa de texto,… (veja aqui outras informações que eu poderia ter perdido)
  • funções ou outras configurações de segurança
  • tipos compostos
  • mesas de brinde
  • FDW e tabelas estrangeiras

Isso é realmente útil para os casos em que o dump que você deseja restaurar é de uma versão de esquema de banco de dados diferente (por exemplo, com Debian dbconfig-common, Flyway ou Liquibase / DB-Manul) do que o banco de dados no qual você deseja restaurá-lo.

Eu também tenho uma versão que exclui "tudo, exceto duas tabelas e o que lhes pertence" (uma sequência, testada manualmente, desculpe, eu sei, chata) no caso de alguém estar interessado; o diff é pequeno. Entre em contato comigo ou consulte este repositório, se estiver interessado.

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

Testado, exceto adições posteriores ( extensionscontribuído por Clément Prévost ), no PostgreSQL 9.6 ( jessie-backports). Remoção agregada testada em 9.6 e 12.2, remoção de procedimento testada em 12.2 também. Correções de bugs e melhorias adicionais são bem-vindas!

mirabilos
fonte
Há erros no script acima, pois ele não distingue entre funções e procedimentos: DROP FUNCTIONfalha em um procedimento e vice-versa. Eu modifiquei a seção de função para isso: AND pp.prokind ='f' -- FunctionouAND pp.prokind ='p' -- Procedure
BogeyMan
1
@ BogeyMan Isso não é um erro, a omissão de funções agregadas foi documentada e o script foi documentado para ser testado apenas na 9.6. Mas levei o seu comentário a sério e o adaptei para lidar com agregados ( proisagg) em ≤ 10.x e agregados e procedimentos ( prokind) em ≥ 11 (verificado dinamicamente) e testei os dois ☻ obrigado pela dica.
mirabilos 29/03
8

Essa é uma pergunta realmente interessante, e você poderá fazer isso de várias maneiras. Espero que isso seja útil para você.

  1. Eliminando e recriando o esquema atual

Aqui, em geral, temos um publicesquema por padrão. Então, eu estou usando isso como uma instância.

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

Se você estiver usando o PostgreSQL 9.3 ou superior, também poderá ser necessário restaurar as concessões padrão.

Prós:

Isso limpará um esquema inteiro e o recriará como um novo.

Contras:

Você vai perder outras entidades também como Functions, Views, Materialized views, etc.

  1. Usando a busca de todos os nomes de pg_tablestabela da tabela.

O PostgreSQL armazena todas as tabelas em sua tabela de registro denominada pg_table.

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

Como você pode ver, pelo uso da subconsulta, podemos remover todas as tabelas do esquema.

Prós:

Quando as outras entidades de dados são importantes e você deseja excluir apenas as tabelas do esquema, essa abordagem será realmente útil para você.

Mayur
fonte
6

Você precisa soltar tabelas e sequências, eis o que funcionou para mim

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 executar o comando que você pode precisar sudo / su aos postgresusuários ou (detalhes de conexão de exportação PGHOST, PGPORT, PGUSERe PGPASSWORD) e, em seguida,export PGDATABASE=yourdatabase

Muayyad Alsadi
fonte
5

Tarefa Rake para Rails para destruir todas as tabelas no banco de dados atual

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
a professora
fonte
1
Pode ser mais simples / seguro dizer AND table_schema = 'public' em vez de NOT nessa lista.
Steve
Por alguma razão, meu esquema foi criado com dados preenchidos. Este ancinho funciona. Então, depois disso rake db:create, eu corro. Você pode fazer a ponta Steve e remover o código table_name = e mudança ", "para ","e #{ tables }fo#{tables}
Washington Botelho
5

As etapas a seguir podem ser úteis (para usuários Linux):

  1. Primeiro, digite o postgresprompt de comando, seguindo o comando:

    sudo -u postgres psql
  2. Digite o banco de dados por este comando (o nome do meu banco de dados é maoss:):

    \c maoss
  3. Agora digite o comando para descartar todas as tabelas:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
FaridLU
fonte
1
segui os passos no meu ubuntu 19.04, funcionou perfeitamente!
Alexandru-Mihai Manolescu 07/04
1
@FaridLU Ajudou muito, obrigado!
Justin Wood
4

Aprimorei o método bash de jamie cuidando das visualizações, porque ele só respeita o tipo de tabela "tabela base", que é o padrão.

O seguinte código bash exclui as visualizações primeiro e depois todo o 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
fonte
Ótimo roteiro ... apenas usei e funcionou como um encanto. Eu também adicionei uma linha para sequências: 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

em um arquivo em lotes do 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
fonte
2

bem, desde que eu gosto de trabalhar na linha 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' chamará o comando list tables.

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

cut -d ' ' -f 4 agora, canalize sua saída para pegar o quarto campo (ao usar o espaço como separador), que é a tabela.

sedé então utilizado como prefixo a drop tablee sufixo o ;separador de comandos.

| egrep '_d_'- Coloque um greppouco mais e você poderá ser mais seletivo sobre as tabelas que você solta.

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

Nota: conforme escrito, isso gerará linhas falsas para a \dtsaída dos comandos dos cabeçalhos das colunas e o total de linhas no final. Evito isso grepping, mas você pode usar heade tail.

JL Peyret
fonte
2

A maneira mais fácil é abandonar o esquema público, como outros sugeriram nas respostas anteriores. No entanto, este não é um bom caminho. Você nunca sabe o que foi feito com o esquema público que foi esquecido e não foi documentado. Você também não sabe se isso funcionará da mesma maneira no futuro. Na V9, teria sido bom, mas na V10 todos os usuários perderiam o acesso ao esquema e devem ter acesso concedido novamente, caso contrário, seu aplicativo será interrompido. Eu não verifiquei a V11, mas o ponto é que você nunca sabe o que será interrompido ao passar de máquina para máquina, site para site ou versão para versão. Isso também não pode ser feito se você for um usuário que tenha acesso ao banco de dados, mas não ao esquema.

Se você precisar fazer isso de forma programática, as outras respostas acima abordarão isso, mas uma coisa que as respostas acima não consideram é fazer com que o Postgres faça o trabalho para você. Se você usar pg_dump com a opção -c como abaixo:

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

Isso criará um script de restauração do banco de dados com instruções sql que excluirá todas as tabelas.

Se o único objetivo ao fazer a pergunta era excluir as tabelas antes da restauração, sua restauração fará o trabalho por você.

No entanto, se você precisar de algo mais, poderá simplesmente copiar as instruções drop do script sql.

RichardP
fonte