【问题标题】:How to duplicate schemas in PostgreSQL如何在 PostgreSQL 中复制模式
【发布时间】:2013-08-15 12:06:04
【问题描述】:

我有一个带有架构 publicschema_A 的数据库。我需要创建一个与schema_a 具有相同结构的新架构schema_b。 找到下面这个函数,问题是它没有复制外键约束。

CREATE OR REPLACE FUNCTION clone_schema(source_schema text, dest_schema text)
  RETURNS void AS
$BODY$
DECLARE
  object text;
  buffer text;
  default_ text;
  column_ text;
BEGIN
  EXECUTE 'CREATE SCHEMA ' || dest_schema ;

  -- TODO: Find a way to make this sequence's owner is the correct table.
  FOR object IN
    SELECT sequence_name::text FROM information_schema.SEQUENCES WHERE sequence_schema = source_schema
  LOOP
    EXECUTE 'CREATE SEQUENCE ' || dest_schema || '.' || object;
  END LOOP;

  FOR object IN
    SELECT table_name::text FROM information_schema.TABLES WHERE table_schema = source_schema
  LOOP
    buffer := dest_schema || '.' || object;
    EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || source_schema || '.' || object || ' INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING DEFAULTS)';

    FOR column_, default_ IN
      SELECT column_name::text, REPLACE(column_default::text, source_schema, dest_schema) FROM information_schema.COLUMNS WHERE table_schema = dest_schema AND table_name = object AND column_default LIKE 'nextval(%' || source_schema || '%::regclass)'
    LOOP
      EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
    END LOOP;
  END LOOP;

END;
$BODY$  LANGUAGE plpgsql

如何使用外键约束克隆/复制schema_A

【问题讨论】:

  • 如果您想使用 SQL 查询克隆架构,请查看this 答案。

标签: postgresql database-schema foreign-key-relationship postgresql-9.1


【解决方案1】:

我会使用pg_dump 转储没有数据的架构:

-s
--schema-only

只转储对象定义(模式),而不转储数据。

此选项与--data-only 相反。它类似于指定--section=pre-data --section=post-data,但由于历史原因并不完全相同。

(不要将此与 --schema 选项混淆,后者使用“模式”一词的不同含义。)

要仅排除数据库中一部分表的表数据,请参阅--exclude-table-data

pg_dump $DB -p $PORT -n $SCHEMA -s -f filename.pgsql

然后重命名转储中的架构(搜索和替换)并使用psql 恢复它。

psql $DB -f filename.pgsql

外键约束其他架构中引用表被复制以指向相同的架构。
same 架构中的表的引用指向复制的架构中的相应表。

【讨论】:

  • 好的,谢谢!但我想避免使用文件。我正在寻找一种快速的方法。
【解决方案2】:

您可以在不使用文件的情况下从命令行执行此操作:

pg_dump -U user --schema='fromschema' database | sed 's/fromschmea/toschema/g' | psql -U user -d database

注意,这会搜索并替换所有出现的架构名称字符串,因此可能会影响您的数据

【讨论】:

  • 如何避免影响数据?
  • @dani24 您可以转储到文件,然后使用grep -E "^[[:digit:]]+.*fromschema.*" dumpfile | wc -l 计算数据行中模式名称的出现次数。如果结果大于 0,则您的数据包含“fromschema”字符串。
【解决方案3】:

聚会有点晚了,但是这里的一些 sql 可以帮助你:

获取架构 oid:

namespace_id = SELECT oid 
                  FROM pg_namespace 
                 WHERE nspname = '<schema name>';

获取表的 oid:

table_id = SELECT relfilenode 
                FROM pg_class 
               WHERE relnamespace = '<namespace_id>' AND relname = '<table_name>'

获取外键约束:

SELECT con.conname, pg_catalog.pg_get_constraintdef(con.oid) AS condef 
  FROM pg_catalog.pg_constraint AS con 
  JOIN pg_class AS cl ON cl.relnamespace = con.connamespace AND cl.relfilenode = con.conrelid 
 WHERE con.conrelid = '<table_relid>'::pg_catalog.oid AND con.contype = 'f';

可以在here 找到一个很好的 PostgreSQL 系统表资源。此外,您可以通过查看source code 来了解更多关于pg_dump 用于收集转储信息的内部查询。

查看pg_dump 如何收集您的所有数据的最简单方法可能是在其上使用strace,如下所示:

$ strace -f -e sendto -s8192 -o pg_dump.trace pg_dump -s -n <schema>
$ grep -oP '(SET|SELECT)\s.+(?=\\0)' pg_dump.trace

您仍然需要整理大量的语句,但它应该可以帮助您以编程方式拼凑一个克隆工具,避免不得不掉到 shell 中调用 pg_dump

【讨论】:

【解决方案4】:

我将分享我的问题的解决方案,它与一个小添加相同。我需要克隆一个模式,创建一个新的数据库用户并将新模式中所有对象的所有权分配给该用户。

对于以下示例,我们假设引用架构称为 ref_schema,目标架构称为 new_schema。引用架构和其中的所有对象都归名为 ref_user 的用户所有。

1.使用 pg_dump 转储参考架构:

pg_dump -n ref_schema -f dump.sql database_name

2。创建一个名为 new_user 的新数据库用户:

CREATE USER new_user

3.将架构 ref_schema 重命名为 new_schema

ALTER SCHEMA ref_schema RENAME TO new_schema

4.将重命名架构中所有对象的所有权更改为新用户

REASSIGN OWNED BY ref_user TO new_user

5.从转储中恢复原始参考架构

psql -f dump.sql database_name

我希望有人觉得这很有帮助。

【讨论】:

  • 我需要在没有数据的情况下进行复制。解决办法是什么。只需要结构
【解决方案5】:

刚遇到同样的情况。有时我错过了 remap_schema :)
问题 - 以上都没有解决对大型模式至关重要的 Fc - 标准格式。
所以我想出了一些使用它的东西:
下面的伪代码 - 应该可以工作。
需要在 pg_dump 期间重命名源,当然,这可能不是一个选项 :(
Source :

pg_dump --pre-data in sql format
psql rename sosurce to target
pg_dump -Fc --data-only
psql rename back
pg_dump --post-data in sql format

目标

sed source_schema->target_schema pre-data sql |psql
pg_restore Fc dump
sed source_schema->target_schema post-data sql |psql

上面的 sed 通常会包括任何其他操作(比如源和目标之间的不同用户名),但它会快得多,因为数据不会成为文件的一部分

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多