Как я могу отбросить все таблицы в базе данных PostgreSQL?

1047

Как я могу отбросить все таблицы в PostgreSQL, работая из командной строки?

Я не хочу отбрасывать саму базу данных, только все таблицы и все данные в них.

AP257
источник
3
О какой командной строке вы говорите? Мы знаем, что вам нужна реализация Windows PowerShell.
Грег Смит
4
Сожалею. Работая в Unix, после ввода 'psql' в командной строке - так и в самой среде командной строки psql.
AP257
101
DROP SCHEMA общественный каскад; - вздрогнуть
wildplasser
20
@ 0fnt вы должны будете сделать 'CREATE SCHEMA public;' снова добавить новые таблицы (выяснил трудный путь)
nym
4
Кстати, когда вы удаляете public, вы теряете все установленные расширения.
Судо

Ответы:

1382

Если все ваши таблицы находятся в одной схеме, этот подход может работать (код ниже предполагает, что имя вашей схемы public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Если вы используете PostgreSQL 9.3 или более поздней версии, вам также может потребоваться восстановить права по умолчанию.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Дерек Slife
источник
105
Обратите внимание, что при этом также будут удалены все функции, представления и т. Д., Определенные в общедоступной схеме.
Брэд Кох
5
Обратите внимание, что это не приведет к удалению системных таблиц (например, тех, которые начинаются с pg_), поскольку они находятся в другой схеме pg_catalog.
congusbongus
36
Это создаст схему w / OWNER, установленную для пользователя, которого вы вошли в psql как. Это будет конфликтовать с приложениями, которые входят в систему как другой пользователь. В этом случае вам также нужно запустить «ALTER SCHEMA public OWNER to postgres»; (или любому пользователю, которого ваше приложение использует для создания таблиц)
mgojohn
13
Подняв это из другого ответа, вы, вероятно, захотите получить его GRANT ALL ON SCHEMA public TO public;после создания.
Федерико
1
@Federico Почему вы хотите GRANT ALLпосле создания?
425,
410

Вы можете написать запрос для генерации сценария SQL следующим образом:

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

Или:

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

В случае, если некоторые таблицы автоматически отбрасываются из-за каскадной опции в предыдущем предложении.

Кроме того, как указано в комментариях, вы можете отфильтровать таблицы, которые вы хотите удалить по имени схемы:

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

А затем запустите его.

Славная КОПИЯ + ПАСТА также будет работать.

Пабло Санта Круз
источник
15
Я думаю, что вы имели в виду: вы можете написать запрос, как этот ... ... а затем запустить вывод запроса
Винко Vrsalovic
5
выберите 'удалить таблицу, если она существует' '|| tablename ||' "cascade; ' из pg_tables; убедитесь, что таблицы с заглавными буквами также правильно отброшены.
Иво ван дер Вейк
12
Предложение "where schemaname = 'public'", которое LenW добавил в своем ответе, может быть очень полезным для уменьшения объема удаления только для базы данных, которой вы управляете, а не для системной
Гийом Жандр,
8
@jwg: также, потому что иногда у вас нет разрешения drop schema public cascade;, но у вас почти всегда есть права на удаление таблиц.
Беркес
2
Версия для непубличных схем: выберите «удалить таблицу, если существует» «|| schemaname || '». "' || tablename || '" cascade;' из pg_tables, где schemaname = 'user_data';
Людвиг
292

Наиболее приемлемый ответ на момент написания статьи (январь 2014 г.):

drop schema public cascade;
create schema public;

Это работает, однако если ваше намерение состоит в том, чтобы восстановить общедоступную схему в ее первоначальное состояние, это не полностью решит задачу. В pgAdmin III для PostgreSQL 9.3.1, если вы нажмете на «публичную» схему, созданную таким образом, и посмотрите на «панель SQL», вы увидите следующее:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Однако, напротив, новая база данных будет иметь следующее:

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

Для меня я использую веб-фреймворк Python, который создает таблицы базы данных (web2py), используя ранее вызванные проблемы:

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

На мой взгляд, полностью правильный ответ:

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

Также обратите внимание, что для выдачи этих команд в pgAdmin III, я использовал инструмент Query (значок лупы «Выполнение запросов SQL»), или вы можете использовать Plugins-> PSQL Console

Запись

Если у вас установлены какие-либо расширения, они будут отброшены при удалении схемы, поэтому вы должны записать, что вам нужно установить, а затем выполнить инструкции по мере необходимости. Например

CREATE EXTENSION postgis;

пользователь
источник
7
Подтверждено. Двухстрочное решение ( dropтогда create) использовалось для работы с PostgreSQL 9.1. После обновления до 9.3 необходимы два дополнительных grant.
Цзинхао Ши
4
Еще одно подтверждение: используя Django, я получил ту же ошибку; Мне нужно было запустить эти гранты, прежде чем django сможет взаимодействовать с базой данных.
rjh
2
Это работало отлично, за исключением того, что мне также нужно было переустановить некоторые расширения: СОЗДАЙТЕ РАСШИРЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ hstore; СОЗДАТЬ РАСШИРЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ pgcrypto;
шейкер
173

Вы можете удалить все таблицы с

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

ИМО это лучше, чем drop schema public, потому что вам не нужно воссоздавать schemaи восстанавливать все гранты.

Дополнительный бонус в том, что для этого не требуется внешний язык сценариев или копирование-вставка сгенерированного SQL обратно в интерпретатор

Петр Финдейзен
источник
4
Спасибо за публикацию этого! Я не мог использовать drop schemaхитрость, поскольку пользователь не был владельцем схемы, только таблиц. Этот работал, хотя :)
vdboor
Очень чистое и конкретное ... отличное решение, и оно тоже должно быть принято - вы даже можете добавить к предложению where ограничение количества таблиц, которые вы хотите сохранить, как в тех, которые необходимы для расширений, таких как PostGIS ...
DPSSpatial
Я бы предложил изменить эту строку EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; следующим образом: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
Тигр
@tyger Почему? Это выглядит ненужным осложнением для меня. Есть ли возможность инъекции (и действительно ли это исправить, если есть)? [Я не знаю, достаточно ли Postgres настолько глуп, чтобы позволить именам таблиц сделать это возможным] Если это так, вам действительно следует изменить свой комментарий на изменение в ответе (объясняя, почему в комментариях к редактированию).
Auspex
@Auspex Хех, это была какая-то проблема с предыдущим вариантом, когда я делал это. Прямо сейчас не могу вспомнить ...
Тайгер
127

Если все, что вы хотите удалить, принадлежит одному и тому же пользователю, то вы можете использовать:

drop owned by the_user;

Это отбросит все, что принадлежит пользователю.

Это включает в себя материализованные представления, представления, последовательности, триггеры, схемы, функции, типы, агрегаты, операторы, домены и т. Д. (Так, действительно: все ), которым the_userпринадлежит (= создан).

Вы должны заменить the_userдействительное имя пользователя, в настоящее время нет возможности отбросить все для «текущего пользователя». В следующей версии 9.5 будет опция drop owned by current_user.

Более подробная информация в руководстве: http://www.postgresql.org/docs/current/static/sql-drop-owned.html

a_horse_with_no_name
источник
2
Это отбросило все схемы, принадлежащие пользователю (что я не хотел делать).
Питер Л
4
@PeterL: что четко задокументировано в руководстве, но я отредактировал свой пост, чтобы прояснить, что «все» действительно означает все
a_horse_with_no_name
Я бы использовал drop принадлежащий current_user; Таким образом, вам даже не нужно беспокоиться о вводе правильного имени пользователя.
JavaGeek
2
На самом деле очень хорошее решение для меня. Моя база данных и publicсхема принадлежат postgres, но все остальное принадлежит определенному пользователю, поэтому удаление всего принадлежащего этому пользователю очищает базу данных, за исключением схемы.
Auspex
Обратите внимание, что в документации сказано, что он отменит привилегии, но если вы запустите его как обычный пользователь, он не сможет, поэтому он просто удаляет таблицы и тому подобное, что именно то, что я хочу. Ницца!
Четприклс
76

В соответствии с Пабло выше, чтобы просто отказаться от конкретной схемы, в отношении случая:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';
LenW
источник
Я использовал это, который работал для меня. Я полагаю, что where schemaname='public'часть значима?
ibic
1
@ibic Если вы пропустите это, вы можете также попытаться удалить все внутренние таблицы postgres, что, скорее всего, не то, что вам нужно.
Whirlwin
49
drop schema public cascade;

должен сделать свое дело.

Джо Ван Дейк
источник
10
Обратите внимание, что при этом также будут удалены все функции, представления и т. Д., Определенные в общедоступной схеме.
Джо Ван Дайк
6
Кроме того, вам придется заново создать потом, чтобы добавить таблицы обратно CREATE SCHEMA public;. Также см. Stackoverflow.com/a/14286370 для получения дополнительной информации
mikermcneil
29

Вслед за Пабло и LenW, вот одна строка, которая делает все это и подготовку, и затем выполнение:

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

NB: либо установите, либо замените, $PGUSERи $PGDBзначения, которые вы хотите

Тим Диггинс
источник
22

Если у вас есть PL / PGSQL процедурный язык установлен вы можете использовать следующую команду, чтобы удалить все без оболочки / 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();

Вместо того, чтобы вводить это в приглашении "psql", я бы посоветовал вам скопировать его в файл и затем передать этот файл в качестве ввода в psql, используя опции "--file" или "-f":

psql -f clean_all_pg.sql

Кредит, где кредит должен: я написал функцию, но думаю, что запросы (или, по крайней мере, первый) пришли от кого-то из одного из списков рассылки pgsql несколько лет назад. Не помню точно, когда или какой.

Марк Лоуренс
источник
20

Если вы все равно хотите уничтожить все таблицы, вы можете обойтись без таких тонких вещей, как CASCADE, поместив все таблицы в один оператор. Это также ускоряет выполнение.

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

Выполнение этого напрямую:

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

Заменить TRUNCATEс , DROPкак это применимо.

Endre Both
источник
1
если вы не работаете со publicсхемой, не забудьте включить имя схемы в выражение: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')вместо простой передачи имен таблиц.
B12Toaster
15

Я немного изменил ответ Пабло для удобства возврата сгенерированных команд SQL в виде одной строки:

select string_agg('drop table "' || tablename || '" cascade', '; ') 
from pg_tables where schemaname = 'public'
Аде
источник
14

Используйте этот скрипт в 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; $$
Лука Перико
источник
Это sql не удалось для меня. Я использовал SELECT concat ('drop table', tablename, 'cascade;') КАК drop_table_sql ОТ pg_tables WHERE schemaname = 'public'
Кит Джон Хатчисон
1
Должно быть, я что-то не так сделал, Лука. Я просто попробовал это снова, и это сработало.
Кит Джон Хатчисон
11

На всякий случай ... Простой скрипт на Python, который очищает базу данных 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]

Удостоверьтесь, что после копирования это отступ правильно, так как Python полагается на него.

Петр Кочанский
источник
1
работает линия очарование. Я выбрал это, потому что мне нравилось жестко задавать информацию о подключении к БД - последнее, что я хочу сделать, это нажать не на тот БД! и, кроме того, мой список таблиц является движущейся целью.
JL Peyret
9

Вы можете использовать функцию string_agg, чтобы создать разделенный запятыми список, идеально подходящий для DROP TABLE. Из скрипта 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"
Джейми
источник
должно быть #! / bin / sh
Good Person
9

Это действительно интересный вопрос, и вы решите его несколькими способами. Я надеюсь, что это будет полезно для вас.

  1. Путем удаления и воссоздания текущей схемы

Здесь, в общем, у нас есть publicсхема по умолчанию. Итак, я использую это как пример.

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

Если вы используете PostgreSQL 9.3 или более поздней версии, вам также может потребоваться восстановить права по умолчанию.

Плюсы:

Это очистит всю схему и заново создаст ее как новую.

Минусы:

Вы потеряете другие объекты тоже , как Functions, Views, Materialized viewsи т.д.

  1. Используя выборку всех имен pg_tablesтаблиц из таблицы.

PostgreSQL хранит все таблицы в своей таблице записей с именем pg_table.

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

Как видите, с помощью подзапроса мы можем удалить все таблицы из схемы.

Плюсы:

Когда другие объекты данных Важны, и вы просто хотите удалить только таблицы из схемы, этот подход действительно будет вам полезен.

Mayur
источник
1
только то, что мне нужно, спасибо @Mayur
mikaelovi
8

Если вы хотите удалить данные (не удалить таблицу):

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

Или, если вы хотите удалить таблицу, вы можете использовать этот 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
источник
8

Примечание: мой ответ - действительно удалить таблицы и другие объекты базы данных; для удаления всех данных в таблицах, т. е. усечения всех таблиц , Endre Both предоставил аналогично хорошо выполненный оператор (непосредственное выполнение) месяцем позже.

Для тех случаев , когда вы можете не только DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;или что - то, вот автономный SQL скрипт я написал, что сделка безопасным (т.е. вы можете поместить его между BEGIN;и или ROLLBACK;к просто проверить это или COMMIT;на самом деле делать дело) и очищает «все» объекты базы данных… ну, все те, которые используются в базе данных, которую использует наше приложение, или я мог бы разумно добавить, что:

  • триггеры на столах
  • Ограничения на столах (ФК, ПК, CHECK, UNIQUE)
  • индексы
  • VIEWs (нормальный или материализованный)
  • таблицы
  • последовательности
  • подпрограммы (агрегатные функции, функции, процедуры)
  • все схемы nōn-default (то есть не publicвнутренние или DB-внутренние), которыми владеем «мы»: сценарий полезен, когда выполняется как «не суперпользователь базы данных»; суперпользователь может отбросить все схемы (хотя действительно важные из них явно исключены)
  • расширения (добавленные пользователем, но я обычно намеренно оставляю их в)

Не исключены (некоторые преднамеренные; некоторые только потому, что у меня нет примера в нашей БД):

  • publicсхемы (например , для расширения предоставленного материала в них)
  • подборки и другие локали
  • триггеры событий
  • материал для поиска текста ... (см. здесь другие вещи, которые я мог пропустить)
  • роли или другие параметры безопасности
  • составные типы
  • тост столы
  • FDW и зарубежные таблицы

Это действительно полезно в тех случаях, когда дамп, который вы хотите восстановить, имеет другую версию схемы базы данных (например, с Debian dbconfig-common, Flyway или Liquibase / DB-Manul), чем база данных, в которую вы хотите восстановить ее.

У меня также есть версия, которая удаляет «все, кроме двух таблиц и того, что им принадлежит» (последовательность, проверенная вручную, извините, я знаю, скучно), если кто-то заинтересован; разница маленькая. Свяжитесь со мной или проверьте этот репо, если интересно.

SQL

-- Copyright © 2019, 2020
--      mirabilos <t.glaser@tarent.de>
--
-- Provided that these terms and disclaimer and all copyright notices
-- are retained or reproduced in an accompanying document, permission
-- is granted to deal in this work without restriction, including un‐
-- limited rights to use, publicly perform, distribute, sell, modify,
-- merge, give away, or sublicence.
--
-- This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
-- the utmost extent permitted by applicable law, neither express nor
-- implied; without malicious intent or gross negligence. In no event
-- may a licensor, author or contributor be held liable for indirect,
-- direct, other damage, loss, or other issues arising in any way out
-- of dealing in the work, even if advised of the possibility of such
-- damage or existence of a defect, except proven that it results out
-- of said person’s immediate fault when using the work as intended.
-- -
-- Drop everything from the PostgreSQL database.

DO $$
DECLARE
        q TEXT;
        r RECORD;
BEGIN
        -- triggers
        FOR r IN (SELECT pns.nspname, pc.relname, pt.tgname
                FROM pg_catalog.pg_trigger pt, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pt.tgrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pt.tgisinternal=false
            ) LOOP
                EXECUTE format('DROP TRIGGER %I ON %I.%I;',
                    r.tgname, r.nspname, r.relname);
        END LOOP;
        -- constraints #1: foreign key
        FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pcon.contype='f'
            ) LOOP
                EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                    r.nspname, r.relname, r.conname);
        END LOOP;
        -- constraints #2: the rest
        FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pcon.contype<>'f'
            ) LOOP
                EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                    r.nspname, r.relname, r.conname);
        END LOOP;
        -- indicēs
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='i'
            ) LOOP
                EXECUTE format('DROP INDEX %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- normal and materialised views
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind IN ('v', 'm')
            ) LOOP
                EXECUTE format('DROP VIEW %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- tables
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='r'
            ) LOOP
                EXECUTE format('DROP TABLE %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- sequences
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='S'
            ) LOOP
                EXECUTE format('DROP SEQUENCE %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- extensions (only if necessary; keep them normally)
        FOR r IN (SELECT pns.nspname, pe.extname
                FROM pg_catalog.pg_extension pe, pg_catalog.pg_namespace pns
                WHERE pns.oid=pe.extnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
            ) LOOP
                EXECUTE format('DROP EXTENSION %I;', r.extname);
        END LOOP;
        -- aggregate functions first (because they depend on other functions)
        FOR r IN (SELECT pns.nspname, pp.proname, pp.oid
                FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns, pg_catalog.pg_aggregate pagg
                WHERE pns.oid=pp.pronamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pagg.aggfnoid=pp.oid
            ) LOOP
                EXECUTE format('DROP AGGREGATE %I.%I(%s);',
                    r.nspname, r.proname,
                    pg_get_function_identity_arguments(r.oid));
        END LOOP;
        -- routines (functions, aggregate functions, procedures, window functions)
        IF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                WHERE attrelid='pg_catalog.pg_proc'::regclass
                    AND attname='prokind' -- PostgreSQL 11+
            ) THEN
                q := 'CASE pp.prokind
                        WHEN ''p'' THEN ''PROCEDURE''
                        WHEN ''a'' THEN ''AGGREGATE''
                        ELSE ''FUNCTION''
                    END';
        ELSIF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                WHERE attrelid='pg_catalog.pg_proc'::regclass
                    AND attname='proisagg' -- PostgreSQL ≤10
            ) THEN
                q := 'CASE pp.proisagg
                        WHEN true THEN ''AGGREGATE''
                        ELSE ''FUNCTION''
                    END';
        ELSE
                q := '''FUNCTION''';
        END IF;
        FOR r IN EXECUTE 'SELECT pns.nspname, pp.proname, pp.oid, ' || q || ' AS pt
                FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns
                WHERE pns.oid=pp.pronamespace
                    AND pns.nspname NOT IN (''information_schema'', ''pg_catalog'', ''pg_toast'')
            ' LOOP
                EXECUTE format('DROP %s %I.%I(%s);', r.pt,
                    r.nspname, r.proname,
                    pg_get_function_identity_arguments(r.oid));
        END LOOP;
        -- nōn-default schemata we own; assume to be run by a not-superuser
        FOR r IN (SELECT pns.nspname
                FROM pg_catalog.pg_namespace pns, pg_catalog.pg_roles pr
                WHERE pr.oid=pns.nspowner
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'public')
                    AND pr.rolname=current_user
            ) LOOP
                EXECUTE format('DROP SCHEMA %I;', r.nspname);
        END LOOP;
        -- voilà
        RAISE NOTICE 'Database cleared!';
END; $$;

Протестировано, за исключением более поздних дополнений ( extensionsпредоставленных Clément Prévost ), на PostgreSQL 9.6 ( jessie-backports). Удаление агрегатов проверено на 9.6 и 12.2, процедура удаления также проверена на 12.2. Исправления и дальнейшие улучшения приветствуются!

mirabilos
источник
В приведенном выше скрипте есть ошибки, поскольку он не различает функции и процедуры: DROP FUNCTIONне выполняется для процедуры и наоборот. Я изменил раздел функций так: AND pp.prokind ='f' -- FunctionилиAND pp.prokind ='p' -- Procedure
BogeyMan
1
@ BogeyMan Это не ошибка, упущение агрегатных функций было задокументировано, а сценарий документирован для тестирования только на 9.6. Но я принял ваш комментарий близко к сердцу и адаптировал его для обработки агрегатов ( proisagg) на ≤ 10.x и агрегатов и процедур ( prokind) на ≥ 11 (проверено динамически) и протестировал оба - спасибо за подсказку.
Мирабилось
6

Вам нужно отбросить таблицы и последовательности, вот что сработало для меня

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

Перед выполнением команды вам может понадобиться SUDO / су на postgresпользователя или (экспорт соединения деталей PGHOST, PGPORT, PGUSERи PGPASSWORD) , а затемexport PGDATABASE=yourdatabase

Муайяд Алсади
источник
5

Задача Rake для Rails для уничтожения всех таблиц в текущей базе данных

namespace :db do
  # rake db:drop_all_tables
  task drop_all_tables: :environment do
    query = <<-QUERY
      SELECT
        table_name
      FROM
        information_schema.tables
      WHERE
        table_type = 'BASE TABLE'
      AND
        table_schema NOT IN ('pg_catalog', 'information_schema');
    QUERY

    connection = ActiveRecord::Base.connection
    results    = connection.execute query

    tables = results.map do |line|
      table_name = line['table_name']
    end.join ", "

    connection.execute "DROP TABLE IF EXISTS #{ tables } CASCADE;"
  end
end
учитель
источник
1
Может быть проще / безопаснее сказать AND table_schema = 'public', чем NOT IN в этом списке.
Стив
По какой-то причине моя схема была создана с заполненными данными. Эти грабли работают. Так что после rake db:createя запускаю его. Вы можете сделать Steve наконечник и удалить код table_name = и изменения ", "для ","и #{ tables }Ф.О.#{tables}
Вашингтон Botelho
5

Следующие шаги могут быть полезны (для пользователей Linux):

  1. Сначала введите в postgresкомандной строке следующую команду:

    sudo -u postgres psql
  2. Введите базу данных этой командой (мое имя базы данных:) maoss:

    \c maoss
  3. Теперь введите команду для удаления всех таблиц:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
FaridLU
источник
1
следуя инструкциям на моем Ubuntu 19.04, он работал безупречно!
Александру-Михай Манолеску
1
@FaridLU очень помог, спасибо!
Джастин Вуд
4

Я улучшил метод bash от jamie, позаботившись о представлениях, потому что он учитывает только тип таблицы «базовая таблица», который используется по умолчанию.

следующий код Bash сначала удаляет представления, а затем все остальные

#!/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
источник
Отличный сценарий ... просто использовал его и работал как шарм. Я также добавил строку для последовательностей: 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

в командном файле Windows:

@echo off
FOR /f "tokens=2 delims=|" %%G IN ('psql --host localhost --username postgres --command="\dt" YOUR_TABLE_NAME') DO (
   psql --host localhost --username postgres --command="DROP table if exists %%G cascade" sfkb
   echo table %%G dropped
)
Льюис
источник
2

ну, так как мне нравится работать из командной строки ...

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

-c '\dt' вызовет команду списка таблиц.

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

cut -d ' ' -f 4 Теперь передайте его вывод, чтобы получить 4-е поле (при использовании пробела в качестве разделителя), которое является таблицей.

sedзатем используется для добавления префикса a drop tableи суффикса к ;разделителю команд.

| egrep '_d_'- Добавьте еще grepнемного, и вы можете быть более разборчивы в том, какие таблицы вы бросаете.

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

Примечание: как написано, это сгенерирует фиктивные строки для \dtвывода команд заголовков столбцов и итоговых строк в конце. Я избегаю этого путаницей, но вы можете использовать headи tail.

JL Peyret
источник
2

Самый простой способ - удалить общедоступную схему, как предлагали другие в предыдущих ответах. Тем не менее, это НЕ хороший способ. Вы никогда не знаете, что было сделано с публичной схемой, которая с тех пор была забыта и не была задокументирована. Вы также не знаете, будет ли это работать в будущем. В V9 это было бы нормально, но в V10 все ваши пользователи потеряли бы доступ к схеме, и им необходимо было бы снова предоставить доступ, иначе ваше приложение сломается. Я не проверял V11, но дело в том, что вы никогда не знаете, что сломается при переходе с компьютера на компьютер, с сайта на сайт или с версии на версию. Этого также нельзя сделать, если вы являетесь пользователем, который имеет доступ к базе данных, но не к схеме.

Если вам нужно сделать это программно, то другие ответы выше покрывают это, но одна вещь, которую ответы выше не учитывают, - это заставить Postgres выполнить эту работу за вас. Если вы используете pg_dump с опцией -c, как показано ниже:

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

Это создаст скрипт восстановления БД с инструкциями sql, который удалит все таблицы.

Если единственная цель при задании вопроса состояла в том, чтобы удалить таблицы перед восстановлением, то ваше восстановление сделает всю работу за вас.

Однако, если вам это нужно для чего-то другого, вы можете просто скопировать операторы drop из сценария sql.

RichardP
источник