Як я можу скинути всі таблиці в базу даних PostgreSQL?


1041

Як я можу скинути всі таблиці в PostgreSQL, працюючи з командного рядка?

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


3
Про який командний рядок ви говорите? З усього, що ми знаємо, ви шукаєте реалізацію Windows PowerShell.
Грег Сміт

4
Вибачте. Робота над Unix, після введення 'psql' у командному рядку - так оточення командного рядка psql.
AP257,

101
ДРОП СХЕМА громадський КАСКАД; - здригання
wildplasser

20
@ 0fnt вам доведеться робити "СТВОРИТИ СХЕМУ"; додати нові таблиці ще раз (дізнався важкий шлях)
nym

4
До речі, при падінні publicви втрачаєте будь-які встановлені розширення.
судо

Відповіді:


1374

Якщо всі ваші таблиці знаходяться в одній схемі, цей підхід може працювати (нижче код передбачає, що назва вашої схеми 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;

105
Зауважте, що це також видалить усі функції, представлення даних тощо, визначені у загальнодоступній схемі.
Бред Кох

5
Зверніть увагу , що це не призведе до видалення системних таблиць (наприклад, ті , які починаються з pg_) , оскільки вони знаходяться в іншій схемі, pg_catalog.
congusbongus

36
Це створить схему w / OWNER, встановлену для користувача, у якого ви ввійшли в psql. Це призведе до конфлікту із програмами, які увійшли як інший користувач. У такому випадку вам також потрібно запустити "ALTER SCHEMA public ВЛАСНИК на postgres;" (або будь-якому користувачеві, яке ваш додаток використовує для створення таблиць)
mgojohn

13
Вивівши це з іншої відповіді, ви, мабуть, хочете мати GRANT ALL ON SCHEMA public TO public;після створення.
Федеріко

1
@Federico Чому ви хочете GRANT ALLпісля створення?
425nesp

408

Ви можете написати запит для створення такого сценарію 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
Я думаю, ви мали на увазі: Ви можете написати такий запит ... ... А потім запустити вихід запиту
Vinko Vrsalovic

5
виберіть 'drop table, якщо існує' '|| ім'я таблиці ||' "kascade;" від pg_tables; переконається, що таблиці з великими літерами також будуть правильно відкинуті.
Іво ван дер Війк

12
Застереження "де schemaname = 'public" ", яке LenW додав у своїй відповіді, може бути дуже корисним для зменшення обсягу видалення лише до бази даних, якою ви керували, а не до системи
Гійом Джендр

8
@jwg: також тому, що іноді ти не маєш дозволу на це drop schema public cascade;, але ти майже завжди маєш дозволи на викидання таблиць.
berkes

2
Версія для не загальнодоступних схем: виберіть 'drop table, якщо існує' '|| schemaname ||' "." '|| ім'я таблиці ||' "kascade;" з pg_tables, де schemaname = 'user_data';
ludwig

291

Найбільш прийнятою відповіддю на цей текст (січень 2014 року) є:

drop schema public cascade;
create schema public;

Це спрацьовує, однак якщо ваш намір відновити загальнодоступну схему до її незайманого стану, це не повністю виконає завдання. У розділі pgAdmin III для PostgreSQL 9.3.1, якщо ви натиснете на створену таким чином схему "public" і подивіться на "панель 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, я використовував інструмент "Запит" (піктограма лупи "Виконати abritrar SQL запити") або ви можете використовувати додатки-> PSQL консоль

Примітка

Якщо у вас встановлені будь-які розширення, вони будуть скинуті, коли ви скинете схему, тож слід зауважити, що вам потрібно встановити, а потім виконати оператори за необхідності. Напр

CREATE EXTENSION postgis;


7
Підтверджено. Дворядкове рішення ( dropтоді create) використовувалося для роботи над PostgreSQL 9.1. Після оновлення до 9.3 необхідні два додаткові grant.
Jinghao Shi

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

IMO це краще drop schema public, тому що вам не потрібно відтворювати schemaта відновлювати всі гранти.

Додатковий бонус, що для цього не потрібна мова зовнішнього сценарію, а також копіювання вставленого SQL назад до інтерпретатора.


4
Дякуємо, що опублікували це! Я не міг використати drop schemaтрюк, оскільки користувач не був власником схеми, лише таблиць. Цей працював, хоча :)
vdboor

Дуже чисте та специфічне ... чудове рішення, і його слід також прийняти - ви навіть можете додати до пункту де обмеження таблиць, які ви хочете зберегти, як у тих, що потрібні розширеннями, такими як 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

@tyger Чому? Мені це здається зайвим ускладненням. Чи є можливість ін'єкції (і чи справді це виправити, якщо є)? [Я не знаю, чи Postgres досить дурний, щоб дозволити імена таблиць зробити це можливим] Якщо є, ви дійсно повинні змінити свій коментар на редагування у відповіді (пояснення чому в редагуванні коментарів).
Auspex

@Auspex Хе, це було якесь питання з колишнім варіантом, коли я робив це. Не можу зараз згадати ...
tyger

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


2
Це скинуло всі схеми, що належать користувачеві (чого я не хотів робити).
Петро Л

4
@PeterL: це чітко зафіксовано в посібнику, але я відредагував своє повідомлення, щоб зрозуміти, що "все" насправді означає все
a_horse_with_no_name

Я б використовував краплі, що належать current_user; Таким чином, вам навіть не потрібно турбуватися про введення правильного імені користувача.
JavaGeek

2
Насправді дуже хороше рішення для мене. Моя база даних та publicсхема належать postgres, але все інше належить конкретному користувачеві, тому випадання всього, що належить цьому користувачеві, очищає базу даних, за винятком схеми.
Auspex

Зауважте, що в документації написано, що це скасує привілеї, але якщо ви запускаєте це як звичайний користувач, він не може, тож він просто скидає таблиці та подібне, що саме я хочу. Приємно!
ChetPrickles

76

Згідно з Пабло вище, щоб просто відмовитися від конкретної схеми, щодо випадку:

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

Я використав це, що працювало на мене. Я припускаю, що where schemaname='public'роль значна?
ibic

1
@ibic Якщо ви не помічаєте, що можливо, ви можете також спробувати видалити всі внутрішні таблиці postgres, що, швидше за все, не те, що ви хочете.
вир

49
drop schema public cascade;

повинен зробити трюк.


10
Зауважте, що це також видалить усі функції, представлення даних тощо, визначені у загальнодоступній схемі.
Джо Ван Дайк

6
також вам доведеться знову відтворити їх, щоб додати таблиці назад CREATE SCHEMA public;. Також дивіться stackoverflow.com/a/14286370 для отримання додаткової інформації
mikermcneil

29

Слідом за Пабло та Лену, ось однокласник, який робить все як підготовкою, так і виконанням:

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

Примітка: встановіть або замініть $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як це може бути застосовано.


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', ім'я таблиці, 'kascade;') AS 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
працює лінія чарівності. Я вибрав це, тому що мені сподобалось жорстке кодування інформації про з'єднання db - останнє, що я хочу зробити, це потрапити на неправильний db! і, також, мій список таблиць є рухомою ціллю.
JL Peyret

9

Ви можете використовувати функцію string_agg, щоб скласти розділений комою список, ідеально підходить для DROP TABLE. З баш сценарію:

#!/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
Доброї людини

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

8

Примітка: моя відповідь стосується дійсного видалення таблиць та інших об'єктів бази даних; для видалення всіх даних у таблицях, тобто обрізання всіх таблиць , Endre Обидва подав аналогічно добре виконане (пряме виконання) заява через місяць.

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

  • тригери на столах
  • Обмеження на столах (ФК, ПК, CHECK,UNIQUE )
  • indēs
  • VIEWs (нормальна або матеріалізована)
  • столи
  • послідовності
  • підпрограми (сукупні функції, функції, процедури)
  • всі схеми n -n за замовчуванням (тобто не publicабо внутрішні БД) схеми "ми" володіємо: сценарій корисний, коли він працює як "не суперпользователь базы данных"; суперрусер може скинути всі схеми (хоча справді важливі з них явно виключені)
  • розширення (внесені користувачем, але я зазвичай навмисно залишаю їх у)

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

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

Це дійсно корисно у випадках, коли дамп, який ви хочете відновити, має іншу версію схеми бази даних (наприклад, з Debiandbconfig-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. Виправлення помилок та подальші вдосконалення вітаються!


У наведеному вище скрипті є помилки, оскільки він не розрізняє функції та процедури: DROP FUNCTIONвідмова від процедури та навпаки. Я змінив розділ функції на це: AND pp.prokind ='f' -- FunctionабоAND pp.prokind ='p' -- Procedure
BogeyMan

1
@BogeyMan Це не помилка, опущення функцій сукупності було задокументовано, а сценарій був задокументований для тестування лише на 9.6. Але я прийняв ваш коментар до серця і адаптував його для обробки агрегатів ( proisagg) на ≤ 10.x та агрегатів та процедур ( prokind) на ≥ 11 (перевірено динамічно) і протестував обидва ☻ дякую за підказку.
mirabilos

8

Це дійсно цікаве запитання, і ви зможете його виконати кількома способами. Я сподіваюся, що вам це стане в нагоді.

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

Як бачите, За допомогою підзапиту ми можемо видалити цілі таблиці зі схеми.

Плюси:

Коли інші об'єкти даних є важливими, і ви просто хочете видалити лише таблиці зі схеми, такий підхід буде вам дуже корисний.


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', а не НЕ В цьому списку.
Стів

Чомусь була створена моя схема із заповненими даними. Цей граблі працює. Тож після цього rake db:createя запускаю його. Ви можете зробити Steve наконечник і видалити код table_name = і зміни ", "для ","і #{ tables }Ф.О.#{tables}
Вашингтон Botelho

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"

Чудовий сценарій ... просто використовував його і працював як шарм. Я також додав рядок для послідовностей: 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
)

4

Наступні кроки можуть бути корисними (для користувачів 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;

1
слідував крокам на моєму ubuntu 19.04, він працював бездоганно!
Олександру-Міхай Манолеску

1
@FaridLU Допомагав дуже, дякую!
Джастін Вуд

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потім використовується для префікса а drop tableта суфікса ;розділювача команд.

| egrep '_d_'- Складіть його в grepдещо більше, і ви можете бути більш вибіркові щодо того, які таблиці ви кинете.

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

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


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, які видалять усі таблиці.

Якщо єдиною метою задавати питання було видалити таблиці перед відновленням, то відновлення зробить роботу за вас.

Однак якщо вам це потрібно для чогось іншого, ви можете просто скопіювати заяви про падіння із скрипту sql.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.