Xóa tất cả dữ liệu trong cơ sở dữ liệu Postgres


14

Tôi đã tạo một kết xuất db mới từ một máy chủ sản xuất có các cờ --data-only--column-inserts, vì vậy tôi chỉ có một loạt các câu lệnh chèn để chèn dữ liệu khi thực hiện khôi phục trên máy chủ dàn.

pg_dump -h localhost -U adminuser --data-only --column-inserts maindb > maindb.sql

Làm cách nào để xóa tất cả dữ liệu trong cơ sở dữ liệu máy chủ dàn trước, trước khi khôi phục dữ liệu từ kết xuất sản xuất?

Tôi chỉ muốn xóa tất cả dữ liệu vì vậy tôi không phải bỏ và tạo cơ sở dữ liệu và tất cả những thứ đó. Tôi chỉ muốn xóa dữ liệu và chèn dữ liệu mới là tất cả.

Tôi không có tùy chọn để thả và tạo cơ sở dữ liệu vì nhiều lý do. Tôi sẽ phải xóa tất cả dữ liệu và chỉ chèn, vì vậy, bất cứ điều gì cần thiết để tìm cách thực hiện việc này, sẵn sàng thực hiện nhưng cần trợ giúp rõ ràng để bắt đầu.

Tôi cũng cần phải tự động hóa quá trình này. Sẽ tự động hóa "kết xuất dữ liệu từ db sản xuất", sau đó "xóa dữ liệu trên phân tầng db" và sau đó "khôi phục dữ liệu để phân tầng db". Tôi chỉ cần trợ giúp về phần "xóa dữ liệu trên staging db".

Tôi đang chạy trên PostgreSQL 9.5.2

Câu trả lời:


24

Bạn không phải bỏ cơ sở dữ liệu, nó sẽ đủ để thả tất cả các đối tượng trong cơ sở dữ liệu. Điều này có thể được thực hiện bằng cách sử dụng

drop owned by adminuser

Nếu bạn sau đó tạo ra các bãi chứa SQL bao gồm các create tablebáo cáo (vì vậy mà không những --data-onlytùy chọn) tất cả mọi thứ nên được tốt.

Bạn cũng có thể loại bỏ --column-insertssau đó, điều này sẽ làm cho việc nhập nhanh hơn rất nhiều .


Tuy nhiên, nếu bạn muốn xóa mọi thứ, bạn có thể làm điều đó với một chút SQL động:

do
$$
declare
  l_stmt text;
begin
  select 'truncate ' || string_agg(format('%I.%I', schemaname, tablename), ',')
    into l_stmt
  from pg_tables
  where schemaname in ('public');

  execute l_stmt;
end;
$$

Điều này sẽ cắt bớt tất cả các bảng trong lược đồ publicbằng một câu lệnh duy nhất cũng sẽ hoạt động ngay cả khi có nhiều ràng buộc khóa ngoài kết nối tất cả các bảng. Nếu các bảng của bạn trải đều trên nhiều lược đồ, bạn cần thêm chúng vào wheređiều kiện.


tôi thấy ... nó có làm điều tương tự như @ypercube đã đề cập ở trên để sử dụng lệnh này TRUNCATE table1, table2, ... <list of all tables>;không? cả hai có làm điều tương tự không?
uberrebu

1
@babababa: có, câu trả lời của tôi chỉ đơn giản là tạo và chạy câu lệnh đó một cách linh hoạt, vì vậy bạn không phải nhập tất cả các tên bảng và nếu bạn thêm một bảng mới, nó sẽ tự động được đưa vào.
a_horse_with_no_name 2/11/2016

Rất vui, chỉ cần thử nó và nó hoạt động, @ypercube cũng hoạt động ... cảm ơn rất nhiều
uberrebu

6

pg_restore có cờ --clean (hoặc có thể - tạo) sẽ tự động xóa dữ liệu trước khi chạy các hoạt động ..

Tài liệu tuyệt vời sẽ giúp bạn rất nhiều ...

Chỉ cần làm rõ, trong trường hợp nó khó hiểu:

Làm sạch (thả) các đối tượng cơ sở dữ liệu trước khi tạo lại chúng. (Trừ khi --if tồn tại được sử dụng, điều này có thể tạo ra một số thông báo lỗi vô hại, nếu có bất kỳ đối tượng nào không có trong cơ sở dữ liệu đích.)

Điều này sẽ không bỏ cơ sở dữ liệu thực tế .. chỉ các bảng / lượt xem / vv.

Nếu, vì một số lý do, việc bỏ và tạo lại các bảng không được chấp nhận, thì bạn sẽ phải đặt nó nhiều công việc hơn để tạo một tập lệnh tạo ra một data onlykết xuất từ ​​db nguồn, các vấn đề TRUNCATEhoặc DELETEtrong cơ sở dữ liệu đích, sau đó tải dữ liệu kết xuất. Không có cách nhanh chóng / khéo léo để làm điều này, theo như tôi biết.


điều đó - cờ sẽ chỉ xóa dữ liệu và giữ cấu trúc cơ sở dữ liệu và bảng giống nhau nhưng trống?
uberrebu

Nó sẽ phát hành một bảng thả trước khi tạo bảng. Bất kỳ bảng nào tồn tại trong tệp kết xuất. Tôi sẽ HỎI rằng tệp kết xuất chứa thông tin để tạo lại bảng chính xác như trước đây (bao gồm cả FKey, v.v.) .. Nhưng nó thực sự phụ thuộc vào cách bạn tạo tệp kết xuất. Tuy nhiên, vì bạn liên tục đề cập đến "dàn", có vẻ như những gì bạn thực sự tìm kiếm là một cách để điền vào các bảng phân tầng trong kho dữ liệu với dữ liệu từ một db sản xuất. Nếu đó là mục tiêu của bạn, một tệp kết xuất có thể là cách tiếp cận sai ..
Joishi Bodio 2/11/2016

đó không phải là điều tôi đang làm, tôi chỉ muốn xóa dữ liệu..cơ sở dữ liệu và cấu trúc bảng sẽ giữ nguyên và không bị ảnh hưởng ... câu hỏi của tôi khá rõ ràng những gì tôi muốn làm, ngay cả từ tiêu đề
uberrebu

Sau đó, xin lỗi để nói, giải pháp của bạn sẽ khó khăn hơn nhiều.
Joishi Bodio

3
SELECT 'TRUNCATE ' || input_table_name || ' CASCADE;' AS truncate_query FROM(SELECT table_schema || '.' || table_name AS input_table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') AND table_schema NOT LIKE 'pg_toast%') AS information;  

Truy vấn trên sẽ tạo ra các truy vấn cắt ngắn cho tất cả các bảng trong cơ sở dữ liệu.


0

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


Hoàn hảo, đây là mã của tôi cho các tiện ích mở rộng, nó phải được đặt trước các hàm / thủ tục: - tiện ích mở rộng CHO r IN (CHỌN pns.nspname, pe.extname TỪ pg_extension pe, pg_namespace pns WHERE pns.oid = pe.extnamespace AND pns .nspname KHÔNG IN ('information_schema', 'pg_catalog', 'pg_toast')) Định dạng LOOP EXECUTE ('DROP EXTENSION% I;', r.extname); CUỐI KẾT THÚC;
Clément Prévost

@ ClémentPrévost cảm ơn, tôi đã hợp nhất nhận xét của bạn vào mã (hy vọng tôi đã làm đúng, bình luận thiếu định dạng, vui lòng xem lại). Tôi thường để các phần mở rộng không bị xóa một cách có chủ ý (trường hợp sử dụng của tôi đang khôi phục từ các bản sao lưu với các phiên bản lược đồ khác nhau và tôi thường có chính xác một phần mở rộng, PL / pgQuery, đã tải). Nó có thể hữu ích cho một số, mặc dù, vì vậy, cảm ơn bạn!
mirabilos

Hoàn hảo, cảm ơn bạn :)
Clément Prévost
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.