Làm cách nào tôi có thể bỏ tất cả các bảng trong cơ sở dữ liệu PostgreSQL?


1047

Làm cách nào tôi có thể thả tất cả các bảng trong PostgreSQL, hoạt động từ dòng lệnh?

Tôi không muốn bỏ cơ sở dữ liệu, chỉ tất cả các bảng và tất cả dữ liệu trong đó.


3
Bạn đang nói về dòng lệnh nào? Đối với tất cả chúng tôi biết bạn đang tìm kiếm một triển khai Windows PowerShell.
Greg Smith

4
Lấy làm tiếc. Hoạt động trên Unix, sau khi gõ 'psql' tại dòng lệnh - vì vậy chính môi trường dòng lệnh psql.
AP257

101
DROP SCHema công khai CASCADE; - rùng mình
wildplasser

20
@ 0fnt bạn sẽ phải thực hiện 'TẠO SCHema công khai;' để thêm các bảng mới một lần nữa (tìm ra cách khó khăn)
nym

4
BTW, khi bạn thả public, bạn sẽ mất mọi tiện ích mở rộng đã cài đặt.
sudo

Câu trả lời:


1380

Nếu tất cả các bảng của bạn nằm trong một lược đồ duy nhất, cách tiếp cận này có thể hoạt động (mã bên dưới giả định rằng tên của lược đồ của bạn là public)

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

Nếu bạn đang sử dụng PostgreSQL 9.3 trở lên, bạn cũng có thể cần khôi phục các khoản trợ cấp mặc định.

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;

105
Lưu ý rằng điều này cũng sẽ xóa tất cả các chức năng, chế độ xem, vv được xác định trong lược đồ công cộng.
Brad Koch

5
Lưu ý rằng điều này sẽ không loại bỏ các bảng hệ thống (chẳng hạn như các bảng bắt đầu pg_) vì chúng nằm trong một lược đồ khác , pg_catalog.
congusbongus

36
Điều này sẽ tạo ra lược đồ w / OWNER được đặt cho người dùng mà bạn đã đăng nhập vào psql như. Điều này sẽ xung đột với các ứng dụng đăng nhập như một người dùng khác. Trong trường hợp đó, bạn cũng cần chạy "ALTER SCHema công khai chủ sở hữu để đăng bài;" (hoặc cho bất kỳ người dùng nào mà ứng dụng của bạn sử dụng để tạo bảng)
mgojohn

13
Đưa ra điều này từ một câu trả lời khác mà bạn có thể muốn có GRANT ALL ON SCHEMA public TO public;sau khi tạo.
Federico

1
@Federico Tại sao bạn muốn GRANT ALLsau khi tạo?
425nesp

410

Bạn có thể viết một truy vấn để tạo tập lệnh SQL như thế này:

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

Hoặc là:

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

Trong trường hợp một số bảng được tự động loại bỏ do tùy chọn xếp tầng trong câu trước.

Ngoài ra, như đã nêu trong các nhận xét, bạn có thể muốn lọc các bảng bạn muốn thả theo tên lược đồ:

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

Và sau đó chạy nó.

Vinh quang COPY + PASTE cũng sẽ hoạt động.


15
Tôi nghĩ bạn có nghĩa là: Bạn có thể viết một truy vấn như thế này ... ... Và sau đó chạy đầu ra của truy vấn
Vinko Vrsalovic

5
chọn 'thả bảng nếu tồn tại "' | | tablename || '" xếp tầng;' từ pg_tables; sẽ đảm bảo các bảng có chữ hoa cũng được bỏ đúng cách.
Ivo van der Wijk

12
mệnh đề "where schemaname = 'public'" mà LenW thêm vào trong câu trả lời của anh ta có thể rất hữu ích để giảm phạm vi xóa chỉ cho cơ sở dữ liệu mà bạn quản lý chứ không phải cơ sở dữ liệu của hệ thống
Guillaume Gendre

8
@jwg: cũng vậy, vì đôi khi bạn không có quyền drop schema public cascade;, nhưng hầu như bạn luôn có quyền bỏ bảng.
cập bến

2
Phiên bản cho các lược đồ không công khai: chọn 'thả bảng nếu tồn tại "' | | schemaname || '". "' || tablename || '" cascade;' từ pg_tables nơi schemaname = 'user_data';
ludwig

292

Câu trả lời được chấp nhận nhiều nhất trong bài viết này (tháng 1 năm 2014) là:

drop schema public cascade;
create schema public;

Điều này không hoạt động, tuy nhiên nếu ý định của bạn là khôi phục lược đồ công cộng về trạng thái nguyên vẹn thì điều này không hoàn thành nhiệm vụ. Trong pgAdmin III cho PostgreQuery 9.3.1, nếu bạn nhấp vào lược đồ "công khai" được tạo theo cách này và tìm trong "ngăn SQL", bạn sẽ thấy như sau:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

Tuy nhiên, ngược lại, một cơ sở dữ liệu hoàn toàn mới sẽ có những điều sau đây:

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

Đối với tôi sử dụng khung web python tạo các bảng cơ sở dữ liệu (web2py), sử dụng các sự cố đã gây ra trước đây:

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

Vì vậy, theo tôi, câu trả lời hoàn toàn chính xác là:

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

Cũng lưu ý khi phát hành các lệnh này trong pgAdmin III, tôi đã sử dụng công cụ Truy vấn (biểu tượng kính lúp "Thực thi các truy vấn SQL khó hiểu") hoặc bạn có thể sử dụng Plugins-> Bảng điều khiển PSQL

Ghi chú

Nếu bạn có bất kỳ tiện ích mở rộng nào được cài đặt, chúng sẽ bị loại bỏ khi bạn thả lược đồ, vì vậy bạn nên lưu ý những gì bạn cần cài đặt và sau đó thực hiện các câu lệnh khi cần thiết. Ví dụ

CREATE EXTENSION postgis;


7
Đã xác nhận. Giải pháp hai dòng ( dropsau đó create) được sử dụng để hoạt động trên PostgreSQL 9.1. Sau khi nâng cấp lên 9.3, hai phụ grantlà cần thiết.
Jinghao Shi

4
Thêm một xác nhận: sử dụng Django, tôi đã gặp lỗi tương tự; Tôi cần chạy các khoản tài trợ đó trước khi django có thể tương tác với cơ sở dữ liệu.
rjh

2
Điều này hoạt động hoàn hảo, ngoại trừ việc tôi cũng cần cài đặt lại một số tiện ích mở rộng: TẠO EXTENSION NẾU KHÔNG EXISTS hstore; TẠO EXTENSION NẾU KHÔNG EXISTS pgcrypto;
Shacker

173

Bạn có thể thả tất cả các bảng với

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 điều này tốt hơn drop schema public, bởi vì bạn không cần phải tạo lại schemavà khôi phục tất cả các khoản tài trợ.

Phần thưởng bổ sung mà điều này không yêu cầu ngôn ngữ kịch bản bên ngoài, cũng như sao chép SQL đã tạo trở lại trình thông dịch.


4
Cảm ơn bạn đã đăng bài này! Tôi không thể sử dụng drop schemathủ thuật vì người dùng không phải là chủ sở hữu của lược đồ, chỉ các bảng. Cái này hoạt động được :)
vdboor

Rất sạch sẽ và cụ thể ... giải pháp tuyệt vời và cũng nên được chấp nhận - bạn thậm chí có thể thêm vào mệnh đề where để giới hạn các bảng bạn muốn giữ, như trong các phần mở rộng cần thiết như PostGIS ...
DPSSpatial

Tôi sẽ đề nghị thay đổi dòng đó EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; bằng cách này: EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', quote_ident(r.tablename));
tyger

@tyger Tại sao? Nó trông giống như một sự phức tạp không cần thiết với tôi. khả năng tiêm (và điều này thực sự khắc phục nếu có)? [Tôi không biết Postgres có đủ dại dột để cho phép tên bảng biến điều đó thành có thể không] Nếu có, bạn thực sự nên thay đổi nhận xét của mình thành chỉnh sửa trong câu trả lời (giải thích lý do trong phần chỉnh sửa nhận xét).
Auspex

@Auspex Heh, đó là một số vấn đề với biến thể cũ khi tôi đang làm điều đó. Không thể nhớ ngay bây giờ ...
tyger

127

Nếu mọi thứ bạn muốn thả đều thuộc sở hữu của cùng một người dùng, thì bạn có thể sử dụng:

drop owned by the_user;

Điều này sẽ bỏ mọi thứ mà người dùng sở hữu.

Điều đó bao gồm các khung nhìn cụ thể, các khung nhìn, các chuỗi, trình kích hoạt, lược đồ, hàm, loại, tổng hợp, toán tử, miền, v.v (vì vậy, thực sự: mọi thứ ) the_usersở hữu (= được tạo).

Bạn phải thay thế the_userbằng tên người dùng thực tế, hiện tại không có tùy chọn để bỏ mọi thứ cho "người dùng hiện tại". Phiên bản 9.5 sắp tới sẽ có tùy chọn drop owned by current_user.

Thêm chi tiết trong hướng dẫn sử dụng: http://www.postgresql.org/docs/civerse/static/sql-drop-own.html


2
Điều này đã loại bỏ tất cả các lược đồ thuộc sở hữu của người dùng (điều mà tôi không muốn làm).
Peter L

4
@PeterL: được ghi lại rõ ràng trong hướng dẫn, nhưng tôi đã chỉnh sửa bài đăng của mình để làm rõ rằng "mọi thứ" thực sự có nghĩa là tất cả mọi thứ
a_horse_with_no_name

Tôi sẽ sử dụng drop thuộc sở hữu của current_user; Bằng cách này, bạn thậm chí không phải lo lắng về việc nhập đúng tên người dùng.
JavaGeek

2
Thực sự là một giải pháp rất tốt cho tôi. Cơ sở dữ liệu và publiclược đồ của tôi được sở hữu bởi postgres, nhưng mọi thứ khác đều thuộc sở hữu của một người dùng cụ thể, do đó, bỏ mọi thứ thuộc sở hữu của người dùng đó sẽ xóa cơ sở dữ liệu ngoại trừ lược đồ.
Auspex

Lưu ý rằng tài liệu nói rằng nó sẽ thu hồi các đặc quyền nhưng nếu bạn chạy nó như một người dùng bình thường thì không thể, vì vậy nó chỉ bỏ các bảng và những thứ tương tự, đó chính xác là những gì tôi muốn. Đẹp!
ChetPrickles

76

Theo Pablo ở trên, chỉ cần thả từ một lược đồ cụ thể, liên quan đến trường hợp:

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

Tôi đã sử dụng nó, mà làm việc cho tôi. Tôi giả sử where schemaname='public'một phần là đáng kể?
ibic

1
@ibic Nếu bạn bỏ qua rằng bạn cũng có khả năng sẽ cố gắng xóa tất cả các bảng postgres nội bộ, rất có thể đó không phải là điều bạn muốn.
lốc

49
drop schema public cascade;

nên làm thủ thuật.


10
Lưu ý rằng điều này cũng sẽ xóa tất cả các chức năng, chế độ xem, vv được xác định trong lược đồ công cộng.
Joe Van Dyk

6
sau đó bạn sẽ phải tạo lại một lần nữa sau đó để thêm các bảng trở lại CREATE SCHEMA public;. Đồng thời xem stackoverflow.com/a/14286370 để biết thêm thông tin
mikermcneil

29

Theo Pablo và LenW, đây là một lớp lót thực hiện tất cả cả việc chuẩn bị và sau đó thực hiện:

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

NB: hoặc đặt hoặc thay thế $PGUSER$PGDBvới các giá trị bạn muốn


22

Nếu bạn đã cài đặt ngôn ngữ thủ tục PL / PGSQL, bạn có thể sử dụng cách sau để xóa mọi thứ mà không cần tập lệnh bên ngoài 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();

Thay vì nhập cái này vào dấu nhắc "psql", tôi sẽ đề nghị bạn sao chép nó vào một tệp và sau đó chuyển tệp dưới dạng đầu vào sang psql bằng cách sử dụng các tùy chọn "--file" hoặc "-f":

psql -f clean_all_pg.sql

Tín dụng khi tín dụng đáo hạn: Tôi đã viết hàm, nhưng nghĩ rằng các truy vấn (hoặc ít nhất là đầu tiên) đến từ một người nào đó trong một trong các danh sách gửi thư của pssql cách đây nhiều năm. Đừng nhớ chính xác khi nào hoặc cái nào.


20

Nếu bạn muốn nuke tất cả các bảng bằng mọi cách, bạn có thể phân phối với các niceties như CASCADE bằng cách đặt tất cả các bảng vào một câu lệnh. Điều này cũng làm cho việc thực hiện nhanh hơn.

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

Thực hiện nó trực tiếp:

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

Thay thế TRUNCATEbằng DROPnhư áp dụng.


1
khi không hoạt động trên publiclược đồ, đừng quên đưa tên lược đồ vào biểu thức: string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')thay vì chỉ truyền tên bảng.
B12 Toaster

15

Tôi đã sửa đổi câu trả lời của Pablo một chút để thuận tiện cho việc các lệnh SQL được tạo được trả về dưới dạng một chuỗi:

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

14

Sử dụng tập lệnh này trong 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; $$

Đó là thất bại cho tôi. Tôi đã sử dụng concat CHỌN ('bảng thả', tablename, 'cascade;') NHƯ drop_table_sql TỪ pg_tables WHERE schemaname = 'công khai'
Keith John Hutchison

1
Phải là một cái gì đó tôi đã làm sai, Luca. Tôi chỉ cần thử lại và nó hoạt động.
Keith John Hutchison

11

Chỉ trong trường hợp ... Tập lệnh Python đơn giản giúp dọn dẹp cơ sở dữ liệu 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]

Hãy chắc chắn rằng sau khi sao chép nó, thụt lề là đúng vì Python dựa vào nó.


1
công trình một sự quyến rũ. Tôi đã chọn điều này bởi vì tôi thích mã hóa thông tin kết nối db - điều cuối cùng tôi muốn làm là nhấn sai db! và, ngoài ra, danh sách bảng của tôi là một mục tiêu di chuyển.
JL Peyret

9

Bạn có thể sử dụng hàm string_agg để tạo danh sách được phân tách bằng dấu phẩy, hoàn hảo cho DROP TABLE. Từ một tập lệnh 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"

nên là #! / bin / sh
Người tốt

8

Nếu bạn muốn xóa dữ liệu (không xóa bảng):

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

Hoặc nếu bạn muốn thả bảng, bạn có thể sử dụng sql này:

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

Lưu ý: câu trả lời của tôi là về việc thực sự xóa các bảng và các đối tượng cơ sở dữ liệu khác; để xóa tất cả dữ liệu trong các bảng, tức là cắt bớt tất cả các bảng , Endre Cả hai đã cung cấp một câu lệnh (thực thi trực tiếp) được thực hiện tốt tương tự một tháng sau đó.

Đối với các trường hợp bạn không thể DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;hoặc một cái gì đó, đây là tập lệnh SQL độc lập mà tôi đã viết, nó an toàn cho giao dịch (nghĩa là bạn có thể đặt nó giữa BEGIN;ROLLBACK;để kiểm tra hoặc COMMIT;thực hiện hành động đó) và thực sự làm việc đó) và Dọn dẹp tất cả các đối tượng cơ sở dữ liệu của thành phố tốt, tất cả những thứ được sử dụng trong cơ sở dữ liệu mà ứng dụng của chúng tôi sử dụng hoặc tôi có thể thêm vào một cách hợp lý, đó là:

  • kích hoạt trên bàn
  • các ràng buộc trên các bảng (FK, PK CHECK,, UNIQUE)
  • chỉ dẫn
  • VIEWs (bình thường hoặc vật chất hóa)
  • những cái bàn
  • trình tự
  • thói quen (tổng hợp chức năng, chức năng, thủ tục)
  • tất cả các schemata mặc định (tức là không publichoặc DB-Internal), chúng tôi sở hữu: kịch bản này rất hữu ích khi được chạy dưới dạng không phải là một siêu người dùng cơ sở dữ liệu. một siêu người dùng có thể loại bỏ tất cả các schemata (mặc dù những cái thực sự quan trọng vẫn bị loại trừ rõ ràng)
  • tiện ích mở rộng (do người dùng đóng góp nhưng tôi thường cố tình để chúng trong)

Không bị rơi là (một số cố ý; một số chỉ vì tôi không có ví dụ trong DB của chúng tôi):

  • các publicgiản đồ (ví dụ như cho các công cụ mở rộng-cung cấp trong họ)
  • collations và các công cụ địa phương khác
  • kích hoạt sự kiện
  • công cụ tìm kiếm văn bản, lòng (xem ở đây để biết những thứ khác tôi có thể đã bỏ lỡ)
  • vai trò hoặc cài đặt bảo mật khác
  • loại hỗn hợp
  • bàn nướng bánh mì
  • Bảng FDW và nước ngoài

Điều này thực sự hữu ích cho các trường hợp khi kết xuất mà bạn muốn khôi phục thuộc phiên bản lược đồ cơ sở dữ liệu khác (ví dụ với Debian dbconfig-common, Flyway hoặc Liquibase / DB-Manul) so với cơ sở dữ liệu bạn muốn khôi phục.

Tôi cũng đã có một phiên bản xóa tất cả mọi thứ ngoại trừ hai bảng và những gì thuộc về họ (một chuỗi, được kiểm tra thủ công, xin lỗi, tôi biết, nhàm chán) trong trường hợp ai đó quan tâm; khác biệt là nhỏ. Liên hệ với tôi hoặc kiểm tra repo này nếu quan tâm.

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

Đã thử nghiệm, ngoại trừ các bổ sung sau này (được extensionsđóng góp bởi Clément Prévost ), trên PostgreQuery 9.6 ( jessie-backports). Loại bỏ tổng hợp được thử nghiệm vào ngày 9.6 và 12.2, loại bỏ quy trình cũng được thử nghiệm vào ngày 12.2. Sửa lỗi và cải tiến hơn nữa chào mừng!


Có lỗi trong đoạn mã trên vì nó không phân biệt giữa các hàm và thủ tục: DROP FUNCTIONkhông thành công cho một thủ tục và ngược lại. Tôi đã sửa đổi phần chức năng này: AND pp.prokind ='f' -- FunctionhoặcAND pp.prokind ='p' -- Procedure
BogeyMan

1
@BogeyMan Đó không phải là một lỗi, thiếu sót của các hàm tổng hợp đã được ghi lại và tập lệnh được ghi lại để chỉ được thử nghiệm vào ngày 9.6. Nhưng tôi đã ghi nhận ý kiến ​​của bạn và điều chỉnh nó để xử lý các tổng hợp ( proisagg) trên ≤ 10.x và các tổng hợp và quy trình ( prokind) trên 11 (được kiểm tra động) và kiểm tra cả cảm ơn về gợi ý.
mirabilos

8

Đây là một câu hỏi thực sự thú vị và bạn sẽ giải quyết nó thông qua nhiều cách. Tôi hy vọng điều này sẽ hữu ích cho bạn.

  1. Bằng cách loại bỏ và tạo lại lược đồ hiện tại

Ở đây, nói chung, chúng tôi có một publiclược đồ theo mặc định. Vì vậy, tôi đang sử dụng nó như một ví dụ.

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

Nếu bạn đang sử dụng PostgreSQL 9.3 trở lên, bạn cũng có thể cần khôi phục các khoản trợ cấp mặc định.

Ưu điểm:

Điều này sẽ làm sạch toàn bộ Schema và tạo lại nó như một cái mới.

Nhược điểm:

Bạn sẽ mất các đơn vị khác quá như Functions, Views, Materialized viewsvv

  1. Bằng cách sử dụng tìm nạp tất cả các tên pg_tablesbảng từ bảng.

PostgreSQL lưu trữ tất cả các bảng trên bảng ghi của nó có tên pg_table.

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

Như bạn có thể thấy, bằng cách sử dụng truy vấn con, Chúng tôi có thể xóa toàn bộ bảng khỏi lược đồ.

Ưu điểm:

Khi các thực thể dữ liệu khác là Quan trọng và bạn chỉ muốn xóa các bảng khỏi lược đồ, phương pháp này sẽ thực sự hữu ích cho bạn.


6

Bạn cần bỏ các bảng và trình tự, đây là những gì làm việc cho tôi

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

trước khi bạn chạy các lệnh bạn có thể cần phải sudo / su cho người postgresdùng hoặc (kết nối xuất khẩu chi tiết PGHOST, PGPORT, PGUSERPGPASSWORD) và sau đóexport PGDATABASE=yourdatabase


5

Tác vụ cào cho Rails để hủy tất cả các bảng trong cơ sở dữ liệu hiện tại

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
Có thể nói đơn giản / an toàn hơn khi nói AND table_schema = 'công khai' thay vì KHÔNG CÓ trong danh sách đó.
Steve

Vì một số lý do, lược đồ của tôi đã được tạo với dữ liệu được điền. Cái cào này hoạt động. Vì vậy, sau khi làm rake db:create, tôi chạy nó. Bạn có thể làm mũi Steve và loại bỏ mã table_name = và thay đổi ", "cho ","#{ tables }fo#{tables}
Washington Botelho

5

Các bước sau có thể hữu ích (Đối với người dùng linux):

  1. Đầu tiên, nhập postgresdấu nhắc lệnh bằng lệnh sau:

    sudo -u postgres psql
  2. Nhập cơ sở dữ liệu bằng lệnh này (tên cơ sở dữ liệu của tôi là maoss:):

    \c maoss
  3. Bây giờ hãy nhập lệnh để thả tất cả các bảng:

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

1
Thực hiện theo các bước trên Ubuntu 19.04 của tôi, nó hoạt động hoàn hảo!
Alexandru-Mihai Manolescu

1
@FaridLU Đã giúp rất nhiều, cảm ơn!
Justin Wood

4

Tôi đã cải tiến phương thức bash từ jamie bằng cách quan tâm đến các khung nhìn vì anh ta chỉ tôn trọng loại bảng "bảng cơ sở" là mặc định.

mã bash sau xóa các khung nhìn trước và sau đó tất cả các phần còn lại

#!/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"

Kịch bản tuyệt vời ... chỉ cần sử dụng nó và làm việc như một lá bùa. Tôi cũng đã thêm một dòng cho chuỗi: 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

trong tệp bó 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

tốt, vì tôi thích làm việc từ dòng lệnh ...

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

-c '\dt' sẽ gọi lệnh bảng danh sách.

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

cut -d ' ' -f 4 bây giờ, đặt đầu ra của nó để lấy trường thứ 4 (khi sử dụng khoảng trắng làm dấu phân cách), đó là bảng.

sedsau đó được sử dụng để tiền tố a drop tablevà hậu tố ;phân tách lệnh.

| egrep '_d_'- Đưa nó vào grepmột số chi tiết và bạn có thể chọn lọc hơn về những bảng bạn thả.

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

Lưu ý: như đã viết, điều này sẽ tạo ra các hàng không có thật cho \dtđầu ra lệnh của các tiêu đề cột và tổng số hàng ở cuối. Tôi tránh điều đó bằng cách grepping, nhưng bạn có thể sử dụng headtail.


2

Cách dễ nhất là bỏ lược đồ công khai như những người khác đã đề xuất trong các câu trả lời trước. Tuy nhiên, đây KHÔNG phải là một cách tốt. Bạn không bao giờ biết những gì đã được thực hiện cho lược đồ công cộng đã bị lãng quên và không được ghi lại. Bạn cũng không biết nếu điều này sẽ làm việc tương tự trong tương lai. Trong V9, nó sẽ ổn, nhưng trong V10, tất cả người dùng của bạn sẽ mất quyền truy cập vào lược đồ và phải được cấp lại quyền truy cập nếu không ứng dụng của bạn sẽ bị hỏng. Tôi chưa kiểm tra V11, nhưng vấn đề là bạn không bao giờ biết cái gì sẽ hỏng khi bạn chuyển từ máy này sang máy khác, trang này sang trang khác hoặc phiên bản sang phiên bản. Nó cũng không thể được thực hiện nếu bạn là người dùng có quyền truy cập vào cơ sở dữ liệu, nhưng không truy cập vào lược đồ.

Nếu bạn cần thực hiện việc này theo chương trình thì các câu trả lời khác ở trên sẽ bao gồm điều này, nhưng một điều mà các câu trả lời ở trên không xem xét là để Postgres thực hiện công việc cho bạn. Nếu bạn sử dụng pg_dump với tùy chọn -c như dưới đây:

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

Điều đó sẽ tạo ra một kịch bản khôi phục DB với các câu lệnh sql sẽ xóa tất cả các bảng.

Nếu mục đích duy nhất khi đặt câu hỏi là xóa các bảng trước khi khôi phục, thì khôi phục của bạn sẽ thực hiện công việc cho bạn.

Tuy nhiên, nếu bạn cần nó cho một cái gì đó khác, bạn chỉ cần sao chép các câu lệnh thả từ tập lệnh sql.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.