代码之家  ›  专栏  ›  技术社区  ›  Hoff

Postgres:在从bash脚本重新创建/重新填充之前清除整个数据库

  •  95
  • Hoff  · 技术社区  · 16 年前

    2:将转储导入我的开发数据库

    在步骤1和步骤2之间,我需要清除开发数据库(是否删除所有表?)。如何最好地通过shell脚本实现这一点?到目前为止,看起来是这样的:

    #!/bin/bash
    time=`date '+%Y'-'%m'-'%d'`
    # 1. export(dump) the current production database
    pg_dump -U production_db_name > /backup/dir/backup-${time}.sql
    
    # missing step: drop all tables from development database so it can be re-populated
    
    # 2. load the backup into the development database
    psql -U development_db_name < backup/dir/backup-${time}.sql
    
    6 回复  |  直到 9 年前
        1
  •  221
  •   Малъ Скрылевъ    5 年前

    $ dropdb development_db_name
    $ createdb development_db_name
    

    事实上,我就是这样做的。

        2
  •  105
  •   Steve Bennett    13 年前

    如果您实际上不需要以纯文本.sql脚本文件格式将数据库备份转储到磁盘上,您可以连接 pg_dump pg_restore 在管道上直接连接在一起。

    要删除和重新创建表,可以使用 --clean 的命令行选项 垃圾场

    上述两种情况如下所示:

    pg_dump -U username --clean | pg_restore -U username
    
        3
  •  15
  •   Малъ Скрылевъ    10 年前

    尽管以下行取自windows批处理脚本,但该命令应非常类似:

    psql -U username -h localhost -d postgres -c "DROP DATABASE \"$DATABASE\";"
    

    此命令用于通过实际删除整个数据库来清除它。这个 $DATABASE %DATABASE% )命令中包含一个windows样式的环境变量,其计算结果为数据库名称。您需要用您的 development_db_name .

        4
  •  11
  •   Carlos Júlio    9 年前

    pg_dump -Fc mydb > db.dump
    

    要恢复:

    pg_restore --verbose --clean --no-acl --no-owner -h localhost -U myuser -d my_db db/latest.dump
    
        5
  •  11
  •   Kamil Siwek    7 年前

    如果要清理名为“example_db”的数据库:

    1) 登录到另一个数据库(例如“postgres”):

    psql postgres
    

    DROP DATABASE example_db;
    

    3) 重新创建数据库:

    CREATE DATABASE example_db;
    
        6
  •  10
  •   mirabilos Jai Prakash Rai    6 年前

    注意:我的答案是真正删除表和其他数据库对象;对于 deleting all data in the tables, i.e. truncating all tables 一个月后,Endre和Endre都提供了类似的执行良好(直接执行)的声明。

    如果你不能 DROP SCHEMA public CASCADE; , DROP OWNED BY current_user; 或者,这是我写的一个独立的SQL脚本,它是事务安全的(也就是说,你可以把它放在 BEGIN; ROLLBACK; 只是测试一下或者 COMMIT; 要真正做到这一点)并很好地清理所有数据库对象,我们的应用程序使用的或我可以合理添加的数据库中使用的所有对象,即:

    • 表上的触发器
    • 表上的约束(FK、PK、, CHECK , UNIQUE )
    • 印度
    • VIEW
    • 桌子
    • 序列
    • 例程(聚合函数、函数、过程)
    • 所有nn默认值(即非 public (或DB内部)模式:当作为非数据库超级用户运行时,脚本非常有用;超级用户可以删除 全部的 模式(但真正重要的模式仍被明确排除在外)
    • 扩展(用户贡献,但我通常故意将其保留在中)

    • 这个 公众的 模式(例如,对于其中提供的扩展内容)
    • 事件触发器
    • here 其他我可能错过的东西)
    • 角色或其他安全设置
    • 复合类型
    • FDW和国外表格

    真正地 对于您要恢复的转储为不同数据库架构版本(例如使用Debian)的情况非常有用 dbconfig-common ,Flyway或Liquibase/DB Manul)中,而不是要将其还原到的数据库中。

    我还得到了一个版本,删除除了两个表和属于它们的内容(一个序列,手动测试,对不起,我知道,很无聊),以防有人感兴趣;差别很小。联系我或 check this 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ément Prévost ),在PostgreSQL 9.6上( jessie-backports ). 骨料去除在9.6和12.2中测试,程序去除也在12.2中测试。欢迎进行错误修复和进一步改进!

        7
  •  9
  •   Troy    10 年前

    我用过:

    pg_restore -c -d database_name filename.dump