我有一个包含架构public
和schema_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
?
答案 0 :(得分:21)
您可以在不使用文件的情况下从命令行执行此操作:
pg_dump -U user --schema='fromschema' database | sed 's/fromschmea/toschema/g' | psql -U user -d database
注意,这会搜索并替换作为您的架构名称的所有字符串,因此可能会影响您的数据。
答案 1 :(得分:13)
我会使用pg_dump
转储没有数据的架构:
-s --schema-only
仅转储对象定义(架构),而不转储数据。
此选项与
--data-only
相反。它类似于,但由于历史原因不同,指定--section=pre-data --section=post-data
。(不要将此与
--schema
选项混淆,后者使用不同含义的“schema”一词。)要仅为数据库中的表子集排除表数据,请参阅
--exclude-table-data
。
pg_dump $DB -p $PORT -n $SCHEMA -s -f filename.pgsql
然后重命名转储中的架构(搜索和替换)并使用psql
将其恢复。
psql $DB -f filename.pgsql
引用其他模式中的表的外键约束将被复制为指向相同的模式。
对相同架构中的表的引用指向复制架构中的相应表。
答案 2 :(得分:4)
派对有点晚了但是,这里的一些SQL可以帮助你:
获取架构oid:
namespace_id = SELECT oid
FROM pg_namespace
WHERE nspname = '<schema name>';
获取表格
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系统表的一个很好的资源here。此外,您可以通过查看pg_dump
来了解有关内部查询source code收集转储信息的详细信息。
查看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
。
答案 3 :(得分:3)
我将为我的问题分享一个解决方案,只是增加一点点即可。我需要克隆一个架构,创建一个新的数据库用户,并将新架构中所有对象的所有权分配给该用户。
对于下面的示例,我们假设引用架构称为 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
我希望有人能对此有所帮助。
答案 4 :(得分: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
上面的通常将包括任何其他操作(例如,源和目标之间的用户名不同),但是由于数据将不属于文件的一部分,因此它将更快得多