ฉันจะวางตารางทั้งหมดในฐานข้อมูล PostgreSQL ได้อย่างไร


1043

ฉันจะวางตารางทั้งหมดใน PostgreSQL ทำงานจากบรรทัดคำสั่งได้อย่างไร

ฉันไม่ต้องการวางฐานข้อมูลตัวเองเพียงตารางทั้งหมดและข้อมูลทั้งหมดในพวกเขา


3
บรรทัดคำสั่งที่คุณพูดถึงคืออะไร? เรารู้ว่าคุณกำลังมองหาการติดตั้ง Windows PowerShell
เกร็กสมิ ธ

4
ขอโทษ ทำงานบน Unix หลังจากพิมพ์ 'psql' ที่บรรทัดคำสั่ง - ดังนั้นสภาพแวดล้อมของบรรทัดคำสั่ง psql นั้น
AP257

101
DROP SCHEMA CASCADE สาธารณะ - ตัวสั่น
ทำลายป่า

20
@ 0fnt คุณจะต้องทำ 'สร้างสาธารณะ SCHEMA;' เพื่อเพิ่มตารางใหม่อีกครั้ง (ค้นพบวิธีที่ยาก)
nym

4
BTW เมื่อคุณวางpublicคุณจะสูญเสียส่วนขยายที่ติดตั้งใด ๆ
sudo

คำตอบ:


1377

หากตารางทั้งหมดของคุณอยู่ในสคีมาวิธีการนี้อาจใช้งานได้ (ด้านล่างโค้ดจะถือว่าชื่อสคีมาของคุณคือ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
สิ่งนี้จะสร้างสคีมาด้วยชุดของผู้ใช้ที่คุณเข้าสู่ระบบ psql เป็น สิ่งนี้จะขัดแย้งกับแอปพลิเคชันที่ลงชื่อเข้าใช้ด้วยชื่อผู้ใช้อื่น ในกรณีนั้นคุณต้องเรียกใช้ "ALTER SCHEMA public OWNER เพื่อ postgres" (หรือผู้ใช้แอปของคุณใช้สร้างตาราง)
mgojohn

13
นำสิ่งนี้มาจากคำตอบอื่นที่คุณอาจต้องการGRANT ALL ON SCHEMA public TO public;หลังจากสร้าง
Federico

1
@Federico ทำไมคุณถึงต้องการGRANT ALLหลังจากการสร้าง?
425 พ.ย.

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

จากนั้นเรียกใช้

COPY + PASTE อันทรงเกียรติจะทำงานเช่นกัน


15
ฉันคิดว่าคุณหมายถึง: คุณสามารถเขียนแบบสอบถามเช่นนี้ ... ... แล้วเรียกใช้ผลลัพธ์ของแบบสอบถาม
Vinko Vrsalovic

5
เลือก 'วางตารางหากมีอยู่' '|| tablename ||' "cascade; ' จาก pg_tables; จะทำให้แน่ใจว่าตารางที่มีตัวพิมพ์ใหญ่จะถูกลบเช่นกัน
Ivo van der Wijk

12
ข้อ "where schemaname = 'public'" ที่ LenW ที่เพิ่มเข้ามาในคำตอบของเขาจะมีประโยชน์มากในการลดขอบเขตของการลบเฉพาะฐานข้อมูลที่คุณจัดการและไม่ใช่ของระบบ
Guillaume Gendre

8
@jwg: เพราะบางครั้งคุณไม่ได้รับอนุญาตdrop schema public cascade;แต่คุณเกือบจะมีสิทธิ์ในการวางตาราง
berkes

2
เวอร์ชันสำหรับ schema ที่ไม่ใช่สาธารณะ: เลือก 'ตารางหล่นถ้ามีอยู่ "' || schemaname || '". "' | | tablename || '" cascade;' จาก pg_tables โดยที่ schemaname = 'user_data';
วิก

291

คำตอบที่ได้รับการยอมรับมากที่สุดในขณะที่เขียนนี้ (มกราคม 2014) คือ:

drop schema public cascade;
create schema public;

วิธีนี้ใช้ได้ผลอย่างไรก็ตามถ้าคุณตั้งใจจะเรียกคืนสคีมาสาธารณะกลับสู่สถานะที่บริสุทธิ์นี่จะไม่ทำงานอย่างเต็มที่ ภายใต้ pgAdmin III สำหรับ PostgreSQL 9.3.1 หากคุณคลิกที่สคีมา "สาธารณะ" ที่สร้างขึ้นด้วยวิธีนี้และดูใน "บานหน้าต่าง SQL" คุณจะเห็นสิ่งต่อไปนี้:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

อย่างไรก็ตามในทางตรงกันข้ามฐานข้อมูลใหม่จะมีดังต่อไปนี้:

-- Schema: public

-- DROP SCHEMA public;

CREATE SCHEMA public
  AUTHORIZATION postgres;

GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public
  IS 'standard public schema';

สำหรับฉันใช้ python web framework ที่สร้างตารางฐานข้อมูล (web2py) โดยใช้ปัญหาที่เกิดขึ้นในอดีต:

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

ดังนั้นในใจของฉันคำตอบที่ถูกต้องคือ:

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public IS 'standard public schema';

นอกจากนี้โปรดทราบว่าให้ออกคำสั่งเหล่านี้ใน pgAdmin III ฉันใช้เครื่องมือ Query (ไอคอนรูปแว่นขยาย "เรียกใช้คำสั่ง SQL ที่ไม่เหมาะสม") หรือคุณสามารถใช้ปลั๊กอิน -> คอนโซล PSQL

บันทึก

หากคุณมีการติดตั้งส่วนขยายใด ๆ พวกเขาจะลดลงเมื่อคุณวางสคีมาดังนั้นคุณควรจดบันทึกสิ่งที่คุณต้องการติดตั้งแล้วดำเนินการคำสั่งตามความจำเป็น เช่น

CREATE EXTENSION postgis;


7
ได้รับการยืนยัน โซลูชันสองบรรทัด ( dropจากนั้นcreate) ใช้เพื่อทำงานกับ PostgreSQL 9.1 หลังจากอัพเกรดเป็น 9.3 grantจำเป็นต้องเพิ่มทั้งสองอย่าง
Jinghao Shi

4
อีกหนึ่งยืนยัน: ใช้ Django ฉันได้รับข้อผิดพลาดเดียวกัน ฉันต้องการเรียกใช้ทุนเหล่านี้ก่อนที่ django จะสามารถโต้ตอบกับฐานข้อมูล
rjh

2
สิ่งนี้ทำงานได้อย่างสมบูรณ์ยกเว้นว่าฉันยังต้องติดตั้งส่วนขยายบางส่วนอีกครั้ง: สร้างส่วนขยายหากไม่ได้มีอยู่ สร้างส่วนขยายถ้าไม่มี pgcrypto;
shacker

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 Heh มันเป็นปัญหาบางอย่างกับตัวแปรเดิมเมื่อฉันทำเช่นนั้น จำไม่ได้ว่าตอนนี้ ...
Tyger

127

หากทุกสิ่งที่คุณต้องการที่จะวางเป็นเจ้าของโดยผู้ใช้เดียวกันคุณสามารถใช้:

drop owned by the_user;

สิ่งนี้จะลดทุกอย่างที่ผู้ใช้เป็นเจ้าของ

ซึ่งรวมถึงมุมมอง materialized, มุมมอง, ลำดับ, ทริกเกอร์, schemas, ฟังก์ชั่น, ประเภท, มวลรวม, โอเปอเรเตอร์, โดเมนและอื่น ๆ (ดังนั้นจริง ๆ : ทุกอย่าง ) ที่the_userเป็นเจ้าของ (= สร้าง)

คุณต้องแทนที่the_userด้วยชื่อผู้ใช้จริงในขณะนี้ไม่มีตัวเลือกที่จะทิ้งทุกอย่างสำหรับ "ผู้ใช้ปัจจุบัน" ที่จะเกิดขึ้น 9.5 drop owned by current_userรุ่นจะมีตัวเลือก

รายละเอียดเพิ่มเติมในคู่มือ: http://www.postgresql.org/docs/current/static/sql-drop-owned.html


2
สิ่งนี้ทำให้สกีมาทั้งหมดที่ผู้ใช้เป็นเจ้าของ (ซึ่งฉันไม่ต้องการทำ)
Peter L

4
@PeterL: มีเอกสารชัดเจนในคู่มือ แต่ฉันแก้ไขโพสต์เพื่อให้ชัดเจนว่า "ทุกอย่าง" หมายถึงทุกอย่าง
a_horse_with_no_name

ฉันจะใช้เจ้าของปัจจุบันโดยเจ้าของ วิธีนี้คุณไม่ต้องกังวลเกี่ยวกับการพิมพ์ชื่อผู้ใช้ที่ถูกต้อง
JavaGeek

2
จริงๆแล้วเป็นทางออกที่ดีสำหรับฉัน ฐานข้อมูลและpublicสคีมาของฉันเป็นของpostgresแต่ทุกอย่างอื่นเป็นของผู้ใช้ที่เฉพาะเจาะจงดังนั้นการวางทุกสิ่งที่เป็นของผู้ใช้นั้นจะล้างฐานข้อมูลยกเว้นสคีมา
Auspex

โปรดทราบว่าเอกสารประกอบบอกว่ามันจะยกเลิกสิทธิ์ แต่ถ้าคุณเรียกใช้สิ่งนี้ในฐานะผู้ใช้ปกติมันไม่สามารถทำได้ดังนั้นเพียงแค่วางตารางและสิ่งที่คล้ายซึ่งเป็นสิ่งที่ฉันต้องการ ดี!
ChetPrickles

76

ตาม Pablo ด้านบนเพียงแค่วางจาก schema ที่เฉพาะเจาะจงด้วยความเคารพกรณี:

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

ฉันใช้สิ่งนี้ซึ่งใช้ได้กับฉัน ฉันคิดว่าwhere schemaname='public'ส่วนนั้นสำคัญหรือไม่
ibic

1
@ibic หากคุณไม่ทราบว่าคุณอาจลองลบตาราง postgres ภายในทั้งหมดเช่นกันซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ
whirlwin

49
drop schema public cascade;

ควรทำเคล็ดลับ


10
โปรดทราบว่าสิ่งนี้จะลบฟังก์ชั่นมุมมองและอื่น ๆ ทั้งหมดที่กำหนดไว้ในสคีมาสาธารณะ
Joe Van Dyk

6
CREATE SCHEMA public;คุณยังจะต้องสร้างขึ้นอีกครั้งหลังจากนั้นก็จะเพิ่มตารางกลับมาพร้อมกับ ดูstackoverflow.com/a/14286370สำหรับข้อมูลเพิ่มเติม
mikermcneil

29

ติดตาม Pablo และ LenW ต่อไปนี้เป็นหนึ่งในสายการบินที่ทำทุกอย่างทั้งเตรียมและดำเนินการ:

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

NB: ตั้งหรือแทนที่$PGUSERและ$PGDBด้วยค่าที่คุณต้องการ


22

หากคุณมีภาษาขั้นตอนการติดตั้ง PL / PGSQL คุณสามารถใช้สิ่งต่อไปนี้เพื่อลบทุกอย่างโดยไม่ต้องใช้สคริปต์ภายนอกของเชลล์ / Perl

DROP FUNCTION IF EXISTS remove_all();

CREATE FUNCTION remove_all() RETURNS void AS $$
DECLARE
    rec RECORD;
    cmd text;
BEGIN
    cmd := '';

    FOR rec IN SELECT
            'DROP SEQUENCE ' || quote_ident(n.nspname) || '.'
                || quote_ident(c.relname) || ' CASCADE;' AS name
        FROM
            pg_catalog.pg_class AS c
        LEFT JOIN
            pg_catalog.pg_namespace AS n
        ON
            n.oid = c.relnamespace
        WHERE
            relkind = 'S' AND
            n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
            pg_catalog.pg_table_is_visible(c.oid)
    LOOP
        cmd := cmd || rec.name;
    END LOOP;

    FOR rec IN SELECT
            'DROP TABLE ' || quote_ident(n.nspname) || '.'
                || quote_ident(c.relname) || ' CASCADE;' AS name
        FROM
            pg_catalog.pg_class AS c
        LEFT JOIN
            pg_catalog.pg_namespace AS n
        ON
            n.oid = c.relnamespace WHERE relkind = 'r' AND
            n.nspname NOT IN ('pg_catalog', 'pg_toast') AND
            pg_catalog.pg_table_is_visible(c.oid)
    LOOP
        cmd := cmd || rec.name;
    END LOOP;

    FOR rec IN SELECT
            'DROP FUNCTION ' || quote_ident(ns.nspname) || '.'
                || quote_ident(proname) || '(' || oidvectortypes(proargtypes)
                || ');' AS name
        FROM
            pg_proc
        INNER JOIN
            pg_namespace ns
        ON
            (pg_proc.pronamespace = ns.oid)
        WHERE
            ns.nspname =
            'public'
        ORDER BY
            proname
    LOOP
        cmd := cmd || rec.name;
    END LOOP;

    EXECUTE cmd;
    RETURN;
END;
$$ LANGUAGE plpgsql;

SELECT remove_all();

แทนที่จะพิมพ์สิ่งนี้ในพรอมต์ "psql" ฉันขอแนะนำให้คุณคัดลอกไปยังไฟล์แล้วส่งไฟล์เป็นอินพุตไปยัง psql โดยใช้ตัวเลือก "--file" หรือ "-f":

psql -f clean_all_pg.sql

เครดิตที่เครดิตครบกำหนด: ฉันเขียนฟังก์ชัน แต่คิดว่าข้อความค้นหา (หรืออย่างน้อยคำถามแรก) มาจากใครบางคนในรายการส่งเมล pgsql เมื่อหลายปีก่อน จำไม่ได้ว่าเมื่อไหร่หรืออย่างใดอย่างหนึ่ง


20

หากคุณต้องการทำนุกทุกโต๊ะคุณสามารถแจกจ่ายนิโคตินเช่นแบบเรียงซ้อนโดยการวางตารางทั้งหมดลงในคำสั่งเดียว สิ่งนี้ทำให้การดำเนินการเร็วขึ้น

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
เมื่อไม่ได้ทำงานกับpublicschema อย่าลืมใส่ชื่อ schema ในนิพจน์string_agg(quote_ident(schemaname) || '.' || quote_ident(tablename), ', ')แทนการส่งชื่อตารางเท่านั้น
B12Toaster

15

ฉันแก้ไขคำตอบของ Pablo เล็กน้อยเพื่อความสะดวกในการให้คำสั่ง SQL ที่สร้างขึ้นคืนเป็นสตริงเดียว:

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

14

ใช้สคริปต์นี้ใน pgAdmin:

DO $$
DECLARE 
    brow record;
BEGIN
    FOR brow IN (select 'drop table "' || tablename || '" cascade;' as table_name from pg_tables where schemaname = 'public') LOOP
        EXECUTE brow.table_name;
    END LOOP;
END; $$

sql นั้นล้มเหลวสำหรับฉัน ฉันใช้ SELECT concat ('drop table', tablename, 'cascade;') เป็น drop_table_sql จาก pg_tables WHERE schemaname = 'public'
Keith John Hutchison

1
ต้องเป็นสิ่งที่ฉันทำผิด Luca ฉันลองอีกครั้งและใช้งานได้
Keith John Hutchison

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
ทำงานเป็นสายเสน่ห์ ฉันเลือกสิ่งนี้เพราะฉันชอบ hardcoding ข้อมูลการเชื่อมต่อฐานข้อมูล - สิ่งสุดท้ายที่ฉันต้องการทำคือกดปุ่มผิด! และรายการตารางของฉันก็เป็นเป้าหมายที่เคลื่อนไหวได้
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;ทำจริงโฉนด) และ ล้างค่าวัตถุฐานข้อมูล“ ทั้งหมด” …ทั้งหมดที่ใช้ในฐานข้อมูลที่แอปพลิเคชันของเราใช้หรือฉันอาจเพิ่มอย่างสมเหตุสมผลซึ่งก็คือ:

  • ทริกเกอร์บนตาราง
  • ข้อ จำกัด ในตาราง (FK, PK CHECK,, UNIQUE)
  • ดัชนี
  • VIEWs (ปกติหรือปรากฏขึ้น)
  • ตาราง
  • ลำดับ
  • รูทีน (ฟังก์ชั่นรวม, ฟังก์ชั่น, ขั้นตอน)
  • publicschemata nōn-default (เช่นไม่ใช่หรือ DB-internal) schemata“ เรา” เป็นของตัวเอง: สคริปต์นี้มีประโยชน์เมื่อรันเป็น“ ไม่ใช่ superuser ฐานข้อมูล”; superuser สามารถปล่อยschemata ทั้งหมด (อันที่สำคัญจริงๆยังคงยกเว้นอย่างชัดเจน)
  • ส่วนขยาย (สนับสนุนโดยผู้ใช้ แต่โดยปกติฉันจงใจปล่อยไว้)

ไม่ลดลงเป็น (บางเจตนาบางเพียงเพราะฉันไม่มีตัวอย่างในฐานข้อมูลของเรา):

  • publicสคี (เช่นสำหรับสิ่งที่ส่วนขยายที่ให้ไว้ในพวกเขา)
  • การเรียงหน้าและสิ่งอื่น ๆ ในโลแคล
  • ทริกเกอร์เหตุการณ์
  • เนื้อหาการค้นหาข้อความ ... (ดูที่นี่สำหรับสิ่งอื่นที่ฉันอาจพลาด)
  • บทบาทหรือการตั้งค่าความปลอดภัยอื่น ๆ
  • ประเภทคอมโพสิต
  • ตารางขนมปังปิ้ง
  • FDW และตารางต่างประเทศ

นี่คือจริงๆมีประโยชน์สำหรับกรณีที่การถ่ายโอนข้อมูลที่คุณต้องการที่จะเรียกคืนเป็นรุ่นคีมาฐานข้อมูลที่แตกต่างกัน (เช่นกับ Debian dbconfig-common, เสียหายหรือ Liquibase / DB-Manul) มากกว่าฐานข้อมูลที่คุณต้องการเรียกคืนมันเข้าไป

ฉันยังมีรุ่นที่ลบ“ ทุกอย่างยกเว้นสองตารางและสิ่งที่เป็นของพวกเขา” (ลำดับการทดสอบด้วยตนเองขอโทษฉันรู้น่าเบื่อ) ในกรณีที่ใครบางคนสนใจ ความต่างมีขนาดเล็ก ติดต่อฉันหรือตรวจสอบ repo นี้ถ้าสนใจ

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émentPré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 su / กับpostgresผู้ใช้หรือ (การเชื่อมต่อการส่งออกรายละเอียดPGHOST, PGPORT, PGUSERและPGPASSWORD) แล้วexport PGDATABASE=yourdatabase


5

Rake task สำหรับ 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
มันอาจจะง่ายกว่า / ปลอดภัยกว่าถ้าจะพูดและ table_schema = 'สาธารณะ' แทนที่จะไม่ใช่ในรายการนั้น
Steve

ด้วยเหตุผลบางอย่างสคีมาของฉันถูกสร้างขึ้นด้วยข้อมูลที่มีประชากร คราดนี้ใช้งานได้ดี หลังจากrake db:createนั้นฉันก็วิ่ง คุณสามารถทำเคล็ดลับสตีฟและลบรหัสtable_name = และการเปลี่ยนแปลง", "สำหรับ","และ#{ tables }สำหรับ#{tables}
วอชิงตัน Botelho

5

ขั้นตอนต่อไปนี้อาจเป็นประโยชน์ (สำหรับผู้ใช้ linux):

  1. ในตอนแรกให้ป้อนpostgresคำสั่งโดยทำตามคำสั่งต่อไปนี้:

    sudo -u postgres psql
  2. ป้อนฐานข้อมูลด้วยคำสั่งนี้ (ชื่อฐานข้อมูลของฉันคือmaoss:):

    \c maoss
  3. ตอนนี้ป้อนคำสั่งสำหรับการดร็อปตารางทั้งหมด:

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

1
ทำตามขั้นตอนในอูบุนตู 19.04 ของฉันมันทำงานได้อย่างไม่มีที่ติ!
Alexandru-Mihai Manolescu

1
@FaridLU ช่วยได้มากขอบคุณ!
Justin Wood

4

ฉันปรับปรุงวิธีทุบตีจาก jamie โดยการดูแลมุมมองเพราะเขาเพียงเคารพประเภทตาราง "ตารางฐาน" ซึ่งเป็นค่าเริ่มต้น

รหัสทุบตีต่อไปนี้จะเป็นการลบมุมมองก่อนจากนั้นส่วนที่เหลือทั้งหมด

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

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 tables

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

cut -d ' ' -f 4 ตอนนี้ไพพ์เอาต์พุตเพื่อคว้าฟิลด์ที่ 4 (เมื่อใช้พื้นที่เป็นตัวคั่น) ซึ่งเป็นตาราง

sedจะถูกใช้เพื่อนำหน้า a drop tableและต่อท้าย;ตัวคั่นคำสั่ง

| egrep '_d_'- วางลงในgrepบางส่วนและคุณสามารถเลือกได้มากขึ้นเกี่ยวกับตารางที่คุณวาง

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

หมายเหตุ: ตามที่เขียนไว้สิ่งนี้จะสร้างแถวปลอมสำหรับ\dtเอาต์พุตคำสั่งของส่วนหัวคอลัมน์และแถวทั้งหมดในตอนท้าย ผมหลีกเลี่ยงการว่าโดย grepping แต่คุณสามารถใช้และheadtail


2

วิธีที่ง่ายที่สุดคือการวางสคีมาสาธารณะตามที่คนอื่น ๆ แนะนำไว้ในคำตอบก่อนหน้า อย่างไรก็ตามนี่ไม่ใช่วิธีที่ดี คุณไม่มีทางรู้ว่าสิ่งที่ทำกับสคีมาสาธารณะที่ถูกลืมไปแล้วและไม่มีการจัดทำเป็นเอกสาร คุณไม่รู้ด้วยซ้ำว่าสิ่งนี้จะได้ผลเหมือนกันในอนาคตหรือไม่ ใน V9 มันน่าจะดี แต่ใน V10 ผู้ใช้ของคุณทุกคนจะเข้าถึงสคีมาได้ไม่เต็มที่และจะต้องได้รับสิทธิ์การเข้าถึงอีกครั้งมิฉะนั้นแอปพลิเคชันของคุณจะแตก ฉันยังไม่ได้ตรวจสอบ V11 แต่ประเด็นก็คือคุณไม่เคยรู้ว่าอะไรจะแตกเมื่อคุณย้ายจากเครื่องหนึ่งไปอีกเครื่องหนึ่งไปยังอีกที่หนึ่งหรือหลายรุ่น นอกจากนี้ยังไม่สามารถทำได้หากคุณเป็นผู้ใช้ที่สามารถเข้าถึงฐานข้อมูล แต่ไม่ใช่สคีมา

หากคุณต้องการทำสิ่งนี้โดยทางโปรแกรมแล้วคำตอบอื่น ๆ ข้างต้นครอบคลุมสิ่งนี้ แต่สิ่งหนึ่งที่คำตอบข้างต้นไม่ได้พิจารณาคือให้ Postgres ทำงานให้คุณ หากคุณใช้ pg_dump พร้อมกับตัวเลือก -c ดังนี้:

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

ที่จะสร้างสคริปต์เรียกคืนฐานข้อมูลด้วยคำสั่ง sql ที่จะลบตารางทั้งหมด

หากจุดประสงค์เดียวในการถามคำถามคือการลบตารางก่อนที่จะกู้คืนการกู้คืนของคุณจะทำงานให้คุณ

อย่างไรก็ตามหากคุณต้องการสิ่งอื่นคุณสามารถคัดลอกคำสั่ง drop จากสคริปต์ sql

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.