31

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

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使用外键约束克隆/复制?

4

5 回答 5

39

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

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

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

于 2014-01-15T17:26:57.320 回答
20

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

引用其他模式中的表的外键约束被复制以指向相同的模式。对同一
模式中的 表的引用指向复制模式中的相应表。

于 2013-08-13T19:22:38.340 回答
7

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

对于以下示例,我们假设引用架构称为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

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

于 2018-09-13T18:19:49.503 回答
4

聚会有点晚了,但是,这里的一些 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';

可以在这里找到 PostgreSQL 系统表的一个很好的资源。此外,您可以通过查看源代码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.

于 2015-01-14T01:35:32.537 回答
0

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

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 通常会包括任何其他操作(比如源和目标之间的不同用户名),但它会快得多,因为数据不会成为文件的一部分

于 2019-02-13T08:41:57.923 回答