Bagaimana saya bisa menjatuhkan semua tabel dalam database PostgreSQL?

1047

Bagaimana saya bisa menghapus semua tabel di PostgreSQL, bekerja dari baris perintah?

Saya tidak ingin menjatuhkan database itu sendiri, hanya semua tabel dan semua data di dalamnya.

AP257
sumber
3
Baris perintah apa yang sedang Anda bicarakan? Sejauh yang kami tahu Anda sedang mencari implementasi Windows PowerShell.
Greg Smith
4
Maaf. Bekerja pada Unix, setelah mengetikkan 'psql' di baris perintah - jadi lingkungan baris perintah psql itu sendiri.
AP257
101
DROP SCHEMA publik CASCADE; - bergidik
wildplasser
20
@ 0tidak, Anda harus melakukan 'CREATE SCHEMA public;' untuk menambah tabel baru lagi (ditemukan dengan cara yang sulit)
nym
4
BTW, ketika Anda drop public, Anda kehilangan ekstensi yang diinstal.
sudo

Jawaban:

1381

Jika semua tabel Anda dalam satu skema tunggal, pendekatan ini bisa berfungsi (kode di bawah ini mengasumsikan bahwa nama skema Anda adalah public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Jika Anda menggunakan PostgreSQL 9.3 atau lebih tinggi, Anda mungkin juga perlu mengembalikan hibah default.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
Derek Slife
sumber
105
Perhatikan bahwa ini juga akan menghapus semua fungsi, tampilan, dll yang ditentukan dalam skema publik.
Brad Koch
5
Perhatikan bahwa ini tidak akan menghapus tabel sistem (seperti yang dimulai dengan pg_) karena mereka berada dalam skema yang berbeda pg_catalog,.
congusbongus
36
Ini akan membuat skema w / OWNER diatur ke pengguna yang Anda login ke psql. Ini akan bertentangan dengan aplikasi yang masuk sebagai pengguna yang berbeda. Dalam hal ini, Anda juga perlu menjalankan "ALTER SCHEMA OWNER publik untuk postgres;" (atau untuk pengguna apa pun yang digunakan aplikasi Anda untuk membuat tabel)
mgojohn
13
Membawa ini dari jawaban lain Anda mungkin ingin memiliki GRANT ALL ON SCHEMA public TO public;setelah membuat.
Federico
1
@ Federico Mengapa Anda ingin GRANT ALLsetelah membuat?
425nesp
410

Anda dapat menulis kueri untuk menghasilkan skrip SQL seperti ini:

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

Atau:

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

Dalam hal beberapa tabel secara otomatis dihapus karena opsi kaskade di kalimat sebelumnya.

Selain itu, sebagaimana dinyatakan dalam komentar, Anda mungkin ingin memfilter tabel yang ingin Anda singkirkan dengan nama skema:

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

Dan kemudian jalankan.

Glorious COPY + PASTE juga akan bekerja.

Pablo Santa Cruz
sumber
15
Saya pikir Anda maksud: Anda dapat menulis kueri seperti ini ... ... Dan kemudian menjalankan output dari kueri
Vinko Vrsalovic
5
pilih 'drop table jika ada "' || tablename || '" cascade;' dari pg_tables; akan memastikan tabel dengan huruf besar juga dijatuhkan dengan benar.
Ivo van der Wijk
12
klausa "di mana schemaname = 'publik'" yang ditambahkan LenW dalam jawabannya dapat sangat berguna untuk mengurangi ruang lingkup penghapusan hanya pada basis data yang Anda kelola dan bukan pada sistem
Guillaume Gendre
8
@ jwg: juga, karena kadang-kadang Anda tidak memiliki izin drop schema public cascade;, tetapi Anda hampir selalu memiliki izin untuk menjatuhkan tabel.
Berkel
2
Versi untuk skema tidak publik: pilih 'drop table jika ada "' || schemaname || '". "' || tablename || '" cascade;' dari pg_tables where schemaname = 'user_data';
ludwig
292

Jawaban yang paling diterima pada penulisan ini (Januari 2014) adalah:

drop schema public cascade;
create schema public;

Ini berhasil, namun jika niat Anda adalah mengembalikan skema publik ke kondisi semula, ini tidak sepenuhnya menyelesaikan tugas. Di bawah pgAdmin III untuk PostgreSQL 9.3.1, jika Anda mengklik skema "publik" yang dibuat dengan cara ini dan mencari di "SQL pane" Anda akan melihat yang berikut:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Namun, sebaliknya database baru akan memiliki yang berikut:

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

Bagi saya menggunakan kerangka web python yang membuat tabel database (web2py), menggunakan masalah yang disebabkan sebelumnya:

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

Jadi menurut saya jawaban yang sepenuhnya benar adalah:

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

Juga perhatikan untuk mengeluarkan perintah-perintah ini di pgAdmin III, saya menggunakan alat Query (ikon kaca pembesar "Jalankan query SQL yang sangat penting") atau Anda bisa menggunakan Plugins-> PSQL Console

Catatan

Jika Anda memiliki ekstensi apa pun yang terpasang, ekstensi itu akan dihapus ketika Anda membatalkan skema, jadi Anda harus mencatat apa yang perlu Anda instal dan kemudian jalankan pernyataan seperlunya. Misalnya

CREATE EXTENSION postgis;

Pengguna
sumber
7
Dikonfirmasi Solusi dua baris ( dropkemudian create) digunakan untuk bekerja pada PostgreSQL 9.1. Setelah memutakhirkan ke 9.3, dua tambahan grantdiperlukan.
Jinghao Shi
4
Satu lagi konfirmasi: menggunakan Django, saya mendapat kesalahan yang sama; Saya perlu menjalankan hibah itu sebelum Django dapat berinteraksi dengan database.
rjh
2
Ini berfungsi dengan baik, kecuali bahwa saya juga perlu menginstal ulang beberapa ekstensi: BUAT EXTENSION JIKA TIDAK ADA yang ada hstore; BUAT EXTENSION JIKA TIDAK ADA pgcrypto;
shacker
173

Anda dapat menjatuhkan semua tabel dengan

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 ini lebih baik daripada drop schema public, karena Anda tidak perlu membuat ulang schemadan mengembalikan semua hibah.

Bonus tambahan bahwa ini tidak memerlukan bahasa skrip eksternal, atau copy-paste SQL yang dihasilkan kembali ke penerjemah.

Piotr Findeisen
sumber
4
Terima kasih telah memposting ini! Saya tidak bisa menggunakan drop schematrik karena pengguna bukan pemilik skema, hanya tabel. Yang ini berhasil :)
vdboor
Sangat bersih dan spesifik ... solusi hebat, dan harus diterima juga - Anda bahkan dapat menambahkan klausa mana untuk membatasi tabel yang ingin Anda pertahankan, seperti pada yang dibutuhkan oleh ekstensi seperti PostGIS ...
DPSSpatial
Saya akan menyarankan untuk mengubah baris itu EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; dengan ini: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger
@tyger Kenapa? Sepertinya komplikasi yang tidak perlu bagi saya. Apakah ada kemungkinan injeksi (dan apakah ini benar-benar memperbaikinya jika ada)? [Saya tidak tahu apakah Postgres cukup bodoh untuk memungkinkan nama tabel memungkinkan]. Jika ada, Anda harus benar-benar mengubah komentar Anda menjadi edit dalam jawaban (menjelaskan mengapa dalam edit komentar).
Auspex
@ Auspex Heh, itu beberapa masalah dengan varian sebelumnya ketika saya melakukan itu. Tidak ingat sekarang ...
tyger
127

Jika semua yang ingin Anda lepas dimiliki oleh pengguna yang sama, maka Anda dapat menggunakan:

drop owned by the_user;

Ini akan menghapus semua yang dimiliki pengguna.

Itu termasuk pandangan terwujud, pandangan, sekuens, pemicu, skema, fungsi, tipe, agregat, operator, domain, dan sebagainya (jadi, sungguh: semuanya ) yang the_usermemiliki (= dibuat).

Anda harus mengganti the_userdengan nama pengguna yang sebenarnya, saat ini tidak ada pilihan untuk meninggalkan semuanya untuk "pengguna saat ini". Versi 9.5 mendatang akan memiliki opsi drop owned by current_user.

Lebih detail dalam manual: http://www.postgresql.org/docs/current/static/sql-drop- owned.html

seekor kuda tanpa nama
sumber
2
Ini membatalkan semua skema yang dimiliki oleh pengguna (yang tidak ingin saya lakukan).
Peter L
4
@PeterL: yang jelas didokumentasikan dalam manual, tetapi saya mengedit posting saya untuk menjelaskan bahwa "segalanya" benar-benar berarti segalanya
a_horse_with_no_name
Saya akan menggunakan drop yang dimiliki oleh current_user; Dengan cara ini Anda bahkan tidak perlu khawatir mengetik nama pengguna yang benar.
JavaGeek
2
Sebenarnya solusi yang sangat bagus untuk saya. Basis data dan publicskema saya dimiliki oleh postgres, tetapi semua yang lain dimiliki oleh pengguna tertentu, jadi menjatuhkan semua yang dimiliki oleh pengguna tersebut akan menghapus basis data kecuali untuk skema tersebut.
Auspex
Perhatikan bahwa dokumentasi mengatakan itu akan mencabut hak istimewa tetapi jika Anda menjalankan ini sebagai pengguna biasa tidak bisa, jadi hanya menjatuhkan tabel dan sejenisnya, yang persis seperti yang saya inginkan. Bagus!
ChetPrickles
76

Seperti Pablo di atas, untuk turun dari skema tertentu, sehubungan dengan kasus:

select 'drop table "' || tablename || '" cascade;' 
from pg_tables where schemaname = 'public';
LenW
sumber
Saya menggunakan ini, yang bekerja untuk saya. Saya menganggap where schemaname='public'bagian itu penting?
ibic
1
@ibic Jika Anda lupa bahwa Anda mungkin berpotensi mencoba menghapus semua tabel postgres internal juga, yang kemungkinan besar bukan yang Anda inginkan.
whirlwin
49
drop schema public cascade;

harus melakukan trik.

Joe Van Dyk
sumber
10
Perhatikan bahwa ini juga akan menghapus semua fungsi, tampilan, dll yang ditentukan dalam skema publik.
Joe Van Dyk
6
Anda juga harus menciptakan kembali setelah itu untuk menambahkan tabel kembali CREATE SCHEMA public;. Lihat juga stackoverflow.com/a/14286370 untuk informasi lebih lanjut
mikermcneil
29

Mengikuti Pablo dan LenW, berikut adalah one-liner yang melakukan semuanya mempersiapkan dan kemudian mengeksekusi:

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

NB: atur atau ganti $PGUSERdan $PGDBdengan nilai yang Anda inginkan

Tim Diggins
sumber
22

Jika Anda memiliki bahasa prosedural PL / PGSQL yang diinstal, Anda dapat menggunakan yang berikut ini untuk menghapus semuanya tanpa skrip eksternal 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();

Daripada mengetikkan ini di prompt "psql", saya sarankan Anda menyalinnya ke file dan kemudian meneruskan file tersebut sebagai input ke psql menggunakan opsi "--file" atau "-f":

psql -f clean_all_pg.sql

Kredit di mana kredit jatuh tempo: Saya menulis fungsinya, tetapi berpikir pertanyaan (atau yang pertama setidaknya) berasal dari seseorang di salah satu milis pgsql tahun yang lalu. Tidak ingat persis kapan atau yang mana.

Mark Lawrence
sumber
20

Jika Anda ingin menghapus semua tabel, Anda bisa membuang basa-basi seperti CASCADE dengan meletakkan semua tabel ke dalam satu pernyataan. Ini juga membuat eksekusi lebih cepat.

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

Menjalankannya secara langsung:

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

Ganti TRUNCATEdengan yang DROPberlaku.

Endre Keduanya
sumber
1
saat tidak beroperasi pada publicskema, jangan lupa untuk memasukkan nama skema dalam ekspresi: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')alih-alih hanya meneruskan nama tabel.
B12Toaster
15

Saya memodifikasi jawaban Pablo sedikit demi kenyamanan agar perintah SQL yang dihasilkan dikembalikan sebagai satu string tunggal:

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

Gunakan skrip ini di 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
sumber
Sql itu gagal untuk saya. Saya menggunakan SELECT concat ('drop table', tablename, 'cascade;') SEBAGAI drop_table_sql DARI pg_tables WHERE schemaname = 'publik'
Keith John Hutchison
1
Pasti sesuatu yang saya lakukan salah, Luca. Saya hanya mencobanya lagi dan berhasil.
Keith John Hutchison
11

Untuk jaga-jaga ... Skrip Python sederhana yang membersihkan database 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]

Pastikan bahwa setelah menyalin lekukan itu benar karena Python bergantung padanya.

Piotr Kochański
sumber
1
bekerja berbaris pesona. Saya memilih ini karena saya suka hardcoding info koneksi db - hal terakhir yang ingin saya lakukan adalah memukul db yang salah! dan, juga, daftar tabel saya adalah target yang bergerak.
JL Peyret
9

Anda dapat menggunakan fungsi string_agg untuk membuat daftar yang dipisahkan koma, cocok untuk DROP TABLE. Dari skrip 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
sumber
seharusnya #! / bin / sh
Orang Baik
8

Jika Anda ingin menghapus data (bukan menghapus tabel):

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

Atau jika Anda ingin tabel drop Anda dapat menggunakan sql ini:

-- 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
sumber
8

Catatan: jawaban saya adalah tentang menghapus tabel dan objek database lainnya; untuk menghapus semua data dalam tabel, yaitu memotong semua tabel , Endre Both telah memberikan pernyataan (eksekusi langsung) yang dijalankan dengan baik sebulan kemudian.

Untuk kasus-kasus di mana Anda tidak bisa hanya DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;atau sesuatu, di sini adalah skrip SQL yang berdiri sendiri yang saya tulis, yang aman untuk transaksi (yaitu Anda dapat meletakkannya di antara BEGIN;dan ROLLBACK;untuk hanya mengujinya atau COMMIT;untuk benar-benar melakukan perbuatan) dan membersihkan "semua" objek basis data ... baik, semua yang digunakan dalam basis data yang digunakan aplikasi kita atau yang dapat saya tambahkan dengan bijaksana, yaitu:

  • pemicu di atas meja
  • kendala pada tabel (FK, PK CHECK,, UNIQUE)
  • indeks
  • VIEWs (normal atau terwujud)
  • meja
  • urutan
  • rutinitas (fungsi agregat, fungsi, prosedur)
  • semua skema nōn-default (yaitu bukan publicatau DB-internal) “we” own: script berguna ketika dijalankan sebagai “bukan superuser basis data”; superuser dapat menghapus semua schemata (yang benar-benar penting masih secara eksplisit dikecualikan)
  • ekstensi (kontribusi pengguna tetapi biasanya saya sengaja membiarkannya)

Tidak jatuh adalah (beberapa disengaja; beberapa hanya karena saya tidak punya contoh dalam DB kami):

  • yang publicskema (misalnya untuk hal-hal ekstensi yang disediakan di dalamnya)
  • koleksi dan barang lokal lainnya
  • pemicu acara
  • hal-hal pencarian teks, ... (lihat di sini untuk hal-hal lain yang mungkin saya lewatkan)
  • peran atau pengaturan keamanan lainnya
  • jenis komposit
  • meja roti panggang
  • FDW dan tabel asing

Ini sangat berguna untuk kasus-kasus ketika dump yang ingin Anda pulihkan adalah versi skema database yang berbeda (misalnya dengan Debian dbconfig-common, Flyway atau Liquibase / DB-Manul) daripada database yang ingin Anda pulihkan.

Saya juga punya versi yang menghapus "semuanya kecuali dua tabel dan apa yang menjadi milik mereka" (urutan, diuji secara manual, maaf, saya tahu, membosankan) jika ada yang tertarik; perbedaannya kecil. Hubungi saya atau periksa repo ini jika tertarik.

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

Diuji, kecuali penambahan selanjutnya ( extensionsdisumbangkan oleh Clément Prévost ), di PostgreSQL 9.6 ( jessie-backports). Penghapusan agregat diuji pada 9.6 dan 12.2, penghapusan prosedur juga diuji pada 12.2. Selamat datang di perbaikan bug dan perbaikan lebih lanjut!

mirabilos
sumber
Ada kesalahan dalam skrip di atas karena tidak membedakan antara fungsi dan prosedur: DROP FUNCTIONgagal untuk suatu prosedur, dan sebaliknya. Saya memodifikasi bagian fungsi untuk ini: AND pp.prokind ='f' -- FunctionatauAND pp.prokind ='p' -- Procedure
BogeyMan
1
@ BogeyMan Itu bukan kesalahan, kelalaian fungsi agregat didokumentasikan dan skrip didokumentasikan untuk diuji pada 9,6 saja. Tapi saya mengambil komentar Anda ke hati dan mengadaptasinya untuk menangani agregat ( proisagg) pada ≤ 10.x dan agregat dan prosedur ( prokind) pada ≥ 11 (diperiksa secara dinamis) dan menguji keduanya ☻ terima kasih atas petunjuknya.
mirabilos
8

Ini adalah pertanyaan yang sangat menarik, dan Anda akan menyelesaikannya dengan berbagai cara. Semoga ini bermanfaat bagi Anda.

  1. Dengan menjatuhkan dan membuat ulang skema saat ini

Di sini, Secara umum, kami memiliki publicskema secara default. Jadi, saya menggunakannya sebagai contoh.

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

Jika Anda menggunakan PostgreSQL 9.3 atau lebih tinggi, Anda mungkin juga perlu mengembalikan hibah default.

Pro:

Ini akan membersihkan seluruh Skema dan membuatnya kembali sebagai yang baru.

Cons:

Anda akan kehilangan entitas lain juga seperti Functions, Views, Materialized views, dll

  1. Dengan menggunakan mengambil semua nama pg_tablestabel dari tabel.

PostgreSQL menyimpan semua tabel pada tabel catatan bernama pg_table.

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

Seperti yang Anda lihat, Dengan menggunakan subquery, Kami dapat menghapus seluruh tabel dari skema.

Pro:

Ketika entitas data lainnya Penting dan Anda hanya ingin menghapus tabel saja dari skema, pendekatan ini akan sangat membantu Anda.

Mayur
sumber
6

Anda perlu menjatuhkan tabel dan urutan, inilah yang bekerja untuk saya

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

sebelum Anda menjalankan perintah Anda mungkin perlu sudo / su ke postgrespengguna atau (koneksi ekspor detail PGHOST, PGPORT, PGUSERdan PGPASSWORD) dan kemudianexport PGDATABASE=yourdatabase

Muayyad Alsadi
sumber
5

Tugas Rake untuk Rails untuk menghancurkan semua tabel dalam database saat ini

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
guru
sumber
1
Mungkin lebih mudah / lebih aman untuk mengatakan AND table_schema = 'publik' daripada TIDAK DALAM daftar itu.
Steve
Untuk beberapa alasan, skema saya dibuat dengan data terpopulasi. Penggaruk ini bekerja. Jadi setelah melakukannya rake db:create, saya jalankan. Anda dapat melakukan Steve ujung dan menghapus kode table_name = dan perubahan ", "untuk ","dan #{ tables }fo#{tables}
Washington Botelho
5

Langkah-langkah berikut mungkin bermanfaat (Untuk pengguna linux):

  1. Pada awalnya, masukkan postgresprompt perintah dengan mengikuti perintah:

    sudo -u postgres psql
  2. Masukkan database dengan perintah ini (nama database saya adalah maoss:):

    \c maoss
  3. Sekarang masukkan perintah untuk menjatuhkan semua tabel:

    DROP SCHEMA public CASCADE;
    CREATE SCHEMA public;
    
    GRANT ALL ON SCHEMA public TO postgres;
    GRANT ALL ON SCHEMA public TO public;
FaridLU
sumber
1
mengikuti langkah-langkah di ubuntu 19.04 saya, ia bekerja dengan sempurna!
Alexandru-Mihai Manolescu
1
@FaridLU Banyak membantu, terima kasih!
Justin Wood
4

Saya meningkatkan metode bash dari jamie dengan menjaga pandangan karena dia hanya menghormati jenis tabel "tabel dasar" yang merupakan default.

mengikuti kode bash menghapus pandangan pertama dan kemudian semua sisanya

#!/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
sumber
Script yang bagus ... hanya menggunakannya dan bekerja seperti mantra. Saya juga menambahkan baris untuk urutan: 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

dalam file batch Windows:

@echo off
FOR /f "tokens=2 delims=|" %%G IN ('psql --host localhost --username postgres --command="\dt" YOUR_TABLE_NAME') DO (
   psql --host localhost --username postgres --command="DROP table if exists %%G cascade" sfkb
   echo table %%G dropped
)
Lewis
sumber
2

baik, karena saya suka bekerja dari baris perintah ...

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

-c '\dt' akan memanggil perintah daftar tabel.

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

cut -d ' ' -f 4 sekarang, pipa outputnya untuk meraih bidang ke-4 (saat menggunakan ruang sebagai pemisah), yang merupakan tabel.

sedkemudian digunakan untuk awalan a drop tabledan suffix ;pemisah perintah.

| egrep '_d_'- Pipa menjadi greplebih banyak dan Anda bisa lebih selektif tentang tabel yang Anda jatuhkan.

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

Catatan: seperti yang ditulis, ini akan menghasilkan baris palsu untuk \dtperintah output header kolom dan total baris di akhir. Saya menghindarinya dengan menangkap, tetapi Anda bisa menggunakan headdan tail.

JL Peyret
sumber
2

Cara termudah adalah dengan menjatuhkan skema publik seperti yang disarankan orang lain dalam jawaban sebelumnya. Namun, ini BUKAN cara yang baik. Anda tidak pernah tahu apa yang telah dilakukan pada skema publik yang sejak itu dilupakan dan tidak didokumentasikan. Anda juga tidak tahu apakah ini akan bekerja sama di masa depan. Di V9, itu akan baik-baik saja, tetapi di V10 semua pengguna Anda akan kehilangan akses ke skema, dan harus diberikan akses lagi jika aplikasi Anda akan rusak. Saya belum memeriksa V11, tetapi intinya adalah Anda tidak pernah tahu apa yang akan rusak ketika Anda berpindah dari satu mesin ke mesin, situs ke situs atau versi ke versi. Ini juga tidak dapat dilakukan jika Anda adalah pengguna yang memiliki akses ke database, tetapi tidak ke skema.

Jika Anda perlu melakukan ini secara terprogram maka jawaban lain di atas mencakup hal ini, tetapi satu hal yang tidak dipertimbangkan oleh jawaban di atas adalah membuat Postgres melakukan pekerjaan untuk Anda. Jika Anda menggunakan pg_dump dengan opsi -c seperti di bawah ini:

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

Itu akan membuat skrip pemulihan DB dengan pernyataan sql yang akan menghapus semua tabel.

Jika satu-satunya tujuan dalam mengajukan pertanyaan adalah untuk menghapus tabel sebelum mengembalikan, maka pengembalian Anda akan bekerja untuk Anda.

Namun, jika Anda membutuhkannya untuk hal lain, Anda cukup menyalin pernyataan drop dari skrip sql.

RichardP
sumber