如何在PostgreSQL中复制模式

35g0bw71  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(6)|浏览(229)

我有一个模式为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

bnlyeluc

bnlyeluc1#

你可以在命令行中完成它,而不使用文件:
第一个月

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

2j4z5cfb

2j4z5cfb2#

我会使用pg_dump来转储没有数据的模式:

-s
--schema-only

字符串
仅转储对象定义(模式),而不是数据。
此选项与--data-only相反。它类似于指定--section=pre-data --section=post-data,但由于历史原因而不完全相同。
(Do不要将其与--schema选项混淆,后者使用的“schema”一词有不同的含义。)
要仅排除数据库中表的子集的表数据,请参见--exclude-table-data

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


然后重命名转储中的模式(搜索和替换),并使用psql还原它。

psql $DB -f filename.pgsql


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

e5njpo68

e5njpo683#

我将分享我的问题的解决方案,这是一个小的补充相同。我需要克隆一个模式,创建一个新的数据库用户,并分配所有对象的所有权在新的模式给该用户。
对于下面的示例,我们假设引用模式名为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.将schema ref_schema 重命名为 new_schema

ALTER SCHEMA ref_schema RENAME TO new_schema

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

REASSIGN OWNED BY ref_user TO new_user

5.从dump中恢复原始引用schema

psql -f dump.sql database_name


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

8tntrjer

8tntrjer4#

有点晚了,但是,这里的一些SQL可以帮助你沿着你的方式:

获取schema oid:

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

字符串

get table's 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

bq9c1y66

bq9c1y665#

只是遇到了同样的。有时我会错过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通常会包括任何其他操作(比如在源和目标之间使用不同的用户名),但是它会快得多,因为数据不会是文件的一部分。

0wi1tuuw

0wi1tuuw6#

CREATE DATABASE [Database to create]
WITH TEMPLATE [Database to copy]
OWNER [Your username];

字符串

相关问题