postgresql 复制架构并在同一数据库中创建具有不同名称的新架构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2370614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Copy schema and create new schema with different name in the same data base
提问by Giri
I there a way to copy the existing schema and generate new schema with another name in the same database in postgres.
我有一种方法可以复制现有模式并在 postgres 的同一数据库中使用另一个名称生成新模式。
回答by Frank Heikens
Use pg_dump to dump your current schema in a SQL-formated file. Open the file, replace the schemaname with the new name and excute this script in your database to create the new schema and all other objects inside this schema.
使用 pg_dump 将当前模式转储到 SQL 格式的文件中。打开文件,用新名称替换 schemaname 并在数据库中执行此脚本以创建新模式和此模式内的所有其他对象。
回答by IdanDavidi
Check out thisPostgreSQL's wiki page. It contains a function for clone_schema
as you required, but this function only clones tables. The page refers to thispost, which contains a function that clones everything you need for the schema. This function worked well for me, I managed to execute it with JDBC API.
查看此PostgreSQL 的 wiki 页面。它包含clone_schema
您需要的函数,但该函数仅克隆表。该页面引用了这篇文章,其中包含一个克隆架构所需的所有内容的函数。这个函数对我来说效果很好,我设法用 JDBC API 执行它。
But I had some problems when the schema names contained -
or capital letters. After a research I found out that the source of the problem is quote_ident()
method. I changes the clone_schema
function to work with any schema names. I share the new function here, hope it will help somebody:
但是当架构名称包含-
或大写字母时,我遇到了一些问题。经过研究,我发现问题的根源在于quote_ident()
方法。我更改了clone_schema
函数以使用任何模式名称。我在这里分享新功能,希望它可以帮助某人:
-- Function: clone_schema(text, text)
-- DROP FUNCTION clone_schema(text, text);
CREATE OR REPLACE FUNCTION clone_schema(
source_schema text,
dest_schema text,
include_recs boolean)
RETURNS void AS
$BODY$
-- This function will clone all sequences, tables, data, views & functions from any existing schema to a new one
-- SAMPLE CALL:
-- SELECT clone_schema('public', 'new_schema', TRUE);
DECLARE
src_oid oid;
tbl_oid oid;
func_oid oid;
object text;
buffer text;
srctbl text;
default_ text;
column_ text;
qry text;
dest_qry text;
v_def text;
seqval bigint;
sq_last_value bigint;
sq_max_value bigint;
sq_start_value bigint;
sq_increment_by bigint;
sq_min_value bigint;
sq_cache_value bigint;
sq_log_cnt bigint;
sq_is_called boolean;
sq_is_cycled boolean;
sq_cycled char(10);
BEGIN
-- Check that source_schema exists
SELECT oid INTO src_oid
FROM pg_namespace
WHERE nspname = source_schema;
IF NOT FOUND
THEN
RAISE EXCEPTION 'source schema % does not exist!', source_schema;
RETURN ;
END IF;
-- Check that dest_schema does not yet exist
PERFORM nspname
FROM pg_namespace
WHERE nspname = dest_schema;
IF FOUND
THEN
RAISE EXCEPTION 'dest schema % already exists!', dest_schema;
RETURN ;
END IF;
EXECUTE 'CREATE SCHEMA "' || dest_schema || '"';
-- Create sequences
-- 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 || '".' || quote_ident(object);
srctbl := '"' || source_schema || '".' || quote_ident(object);
EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
FROM "' || source_schema || '".' || quote_ident(object) || ';'
INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ;
IF sq_is_cycled
THEN
sq_cycled := 'CYCLE';
ELSE
sq_cycled := 'NO CYCLE';
END IF;
EXECUTE 'ALTER SEQUENCE "' || dest_schema || '".' || quote_ident(object)
|| ' INCREMENT BY ' || sq_increment_by
|| ' MINVALUE ' || sq_min_value
|| ' MAXVALUE ' || sq_max_value
|| ' START WITH ' || sq_start_value
|| ' RESTART ' || sq_min_value
|| ' CACHE ' || sq_cache_value
|| sq_cycled || ' ;' ;
buffer := '"' || dest_schema || '".' || quote_ident(object);
IF include_recs
THEN
EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
ELSE
EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
END IF;
END LOOP;
-- Create tables
FOR object IN
SELECT TABLE_NAME::text
FROM information_schema.tables
WHERE table_schema = source_schema
AND table_type = 'BASE TABLE'
LOOP
buffer := '"' || dest_schema || '".' || quote_ident(object);
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE "' || source_schema || '".' || quote_ident(object)
|| ' INCLUDING ALL)';
IF include_recs
THEN
-- Insert records from source table
EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM "' || source_schema || '".' || quote_ident(object) || ';';
END IF;
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;
-- add FK constraint
FOR qry IN
SELECT 'ALTER TABLE "' || dest_schema || '".' || quote_ident(rn.relname)
|| ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';'
FROM pg_constraint ct
JOIN pg_class rn ON rn.oid = ct.conrelid
WHERE connamespace = src_oid
AND rn.relkind = 'r'
AND ct.contype = 'f'
LOOP
EXECUTE qry;
END LOOP;
-- Create views
FOR object IN
SELECT table_name::text,
view_definition
FROM information_schema.views
WHERE table_schema = source_schema
LOOP
buffer := '"' || dest_schema || '".' || quote_ident(object);
SELECT view_definition INTO v_def
FROM information_schema.views
WHERE table_schema = source_schema
AND table_name = quote_ident(object);
EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ;
END LOOP;
-- Create functions
FOR func_oid IN
SELECT oid
FROM pg_proc
WHERE pronamespace = src_oid
LOOP
SELECT pg_get_functiondef(func_oid) INTO qry;
SELECT replace(qry, source_schema, dest_schema) INTO dest_qry;
EXECUTE dest_qry;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION clone_schema(text, text, boolean)
OWNER TO postgres;
回答by Justin Dalrymple
I ran a few tests and found the result is referencing the source schema. So here's my improved version:
我运行了一些测试,发现结果是引用了源模式。所以这是我的改进版本:
-- Function: clone_schema(source text, dest text, include_records boolean default true, show_details boolean default false)
-- DROP FUNCTION clone_schema(text, text, boolean, boolean);
CREATE OR REPLACE FUNCTION clone_schema(
source_schema text,
dest_schema text,
include_recs boolean DEFAULT true,
show_details boolean DEFAULT false)
RETURNS void AS
$BODY$
-- This function will clone all sequences, tables, data, views & functions from any existing schema to a new one
-- SAMPLE CALL:
-- SELECT clone_schema('public', 'new_schema');
-- SELECT clone_schema('public', 'new_schema', TRUE);
-- SELECT clone_schema('public', 'new_schema', TRUE, TRUE);
DECLARE
src_oid oid;
tbl_oid oid;
func_oid oid;
object text;
buffer text;
srctbl text;
default_ text;
column_ text;
qry text;
xrec record;
dest_qry text;
v_def text;
seqval bigint;
sq_last_value bigint;
sq_max_value bigint;
sq_start_value bigint;
sq_increment_by bigint;
sq_min_value bigint;
sq_cache_value bigint;
sq_log_cnt bigint;
sq_is_called boolean;
sq_is_cycled boolean;
sq_cycled char(10);
rec record;
source_schema_dot text = source_schema || '.';
dest_schema_dot text = dest_schema || '.';
BEGIN
-- Check that source_schema exists
SELECT oid INTO src_oid
FROM pg_namespace
WHERE nspname = quote_ident(source_schema);
IF NOT FOUND
THEN
RAISE NOTICE 'source schema % does not exist!', source_schema;
RETURN ;
END IF;
-- Check that dest_schema does not yet exist
PERFORM nspname
FROM pg_namespace
WHERE nspname = quote_ident(dest_schema);
IF FOUND
THEN
RAISE NOTICE 'dest schema % already exists!', dest_schema;
RETURN ;
END IF;
EXECUTE 'CREATE SCHEMA ' || quote_ident(dest_schema) ;
-- Defaults search_path to destination schema
PERFORM set_config('search_path', dest_schema, true);
-- Create sequences
-- 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 = quote_ident(source_schema)
LOOP
EXECUTE 'CREATE SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object);
srctbl := quote_ident(source_schema) || '.' || quote_ident(object);
EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';'
INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ;
IF sq_is_cycled
THEN
sq_cycled := 'CYCLE';
ELSE
sq_cycled := 'NO CYCLE';
END IF;
EXECUTE 'ALTER SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object)
|| ' INCREMENT BY ' || sq_increment_by
|| ' MINVALUE ' || sq_min_value
|| ' MAXVALUE ' || sq_max_value
|| ' START WITH ' || sq_start_value
|| ' RESTART ' || sq_min_value
|| ' CACHE ' || sq_cache_value
|| sq_cycled || ' ;' ;
buffer := quote_ident(dest_schema) || '.' || quote_ident(object);
IF include_recs
THEN
EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
ELSE
EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
END IF;
IF show_details THEN RAISE NOTICE 'Sequence created: %', object; END IF;
END LOOP;
-- Create tables
FOR object IN
SELECT TABLE_NAME::text
FROM information_schema.tables
WHERE table_schema = quote_ident(source_schema)
AND table_type = 'BASE TABLE'
LOOP
buffer := dest_schema || '.' || quote_ident(object);
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || quote_ident(source_schema) || '.' || quote_ident(object)
|| ' INCLUDING ALL)';
IF include_recs
THEN
-- Insert records from source table
EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';';
END IF;
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(%' || quote_ident(source_schema) || '%::regclass)'
LOOP
EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
END LOOP;
IF show_details THEN RAISE NOTICE 'base table created: %', object; END IF;
END LOOP;
-- add FK constraint
FOR xrec IN
SELECT ct.conname as fk_name, rn.relname as tb_name, 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname)
|| ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || replace(pg_get_constraintdef(ct.oid), source_schema_dot, '') || ';' as qry
FROM pg_constraint ct
JOIN pg_class rn ON rn.oid = ct.conrelid
WHERE connamespace = src_oid
AND rn.relkind = 'r'
AND ct.contype = 'f'
LOOP
IF show_details THEN RAISE NOTICE 'Creating FK constraint %.%...', xrec.tb_name, xrec.fk_name; END IF;
--RAISE NOTICE 'DEF: %', xrec.qry;
EXECUTE xrec.qry;
END LOOP;
-- Create functions
FOR xrec IN
SELECT proname as func_name, oid as func_oid
FROM pg_proc
WHERE pronamespace = src_oid
LOOP
IF show_details THEN RAISE NOTICE 'Creating function %...', xrec.func_name; END IF;
SELECT pg_get_functiondef(xrec.func_oid) INTO qry;
SELECT replace(qry, source_schema_dot, '') INTO dest_qry;
EXECUTE dest_qry;
END LOOP;
-- add Table Triggers
FOR rec IN
SELECT
trg.tgname AS trigger_name,
tbl.relname AS trigger_table,
CASE
WHEN trg.tgenabled='O' THEN 'ENABLED'
ELSE 'DISABLED'
END AS status,
CASE trg.tgtype::integer & 1
WHEN 1 THEN 'ROW'::text
ELSE 'STATEMENT'::text
END AS trigger_level,
CASE trg.tgtype::integer & 66
WHEN 2 THEN 'BEFORE'
WHEN 64 THEN 'INSTEAD OF'
ELSE 'AFTER'
END AS action_timing,
CASE trg.tgtype::integer & cast(60 AS int2)
WHEN 16 THEN 'UPDATE'
WHEN 8 THEN 'DELETE'
WHEN 4 THEN 'INSERT'
WHEN 20 THEN 'INSERT OR UPDATE'
WHEN 28 THEN 'INSERT OR UPDATE OR DELETE'
WHEN 24 THEN 'UPDATE OR DELETE'
WHEN 12 THEN 'INSERT OR DELETE'
WHEN 32 THEN 'TRUNCATE'
END AS trigger_event,
'EXECUTE PROCEDURE ' || (SELECT nspname FROM pg_namespace where oid = pc.pronamespace )
|| '.' || proname || '('
|| regexp_replace(replace(trim(trailing '-- Function: clone_schema(text, text)
-- DROP FUNCTION clone_schema(text, text);
CREATE OR REPLACE FUNCTION clone_schema(
source_schema text,
dest_schema text,
include_recs boolean)
RETURNS void AS
$BODY$
-- This function will clone all sequences, tables, data, views & functions from any existing schema to a new one
-- SAMPLE CALL:
-- SELECT clone_schema('public', 'new_schema', TRUE);
DECLARE
src_oid oid;
tbl_oid oid;
func_oid oid;
table_rec record;
seq_rec record;
object text;
sequence_ text;
table_ text;
buffer text;
seq_buffer text;
table_buffer text;
srctbl text;
default_ text;
column_ text;
qry text;
dest_qry text;
v_def text;
seqval bigint;
sq_last_value bigint;
sq_max_value bigint;
sq_start_value bigint;
sq_increment_by bigint;
sq_min_value bigint;
sq_cache_value bigint;
sq_log_cnt bigint;
sq_is_called boolean;
sq_is_cycled boolean;
sq_cycled char(10);
BEGIN
-- Check that source_schema exists
SELECT oid INTO src_oid
FROM pg_namespace
WHERE nspname = source_schema;
IF NOT FOUND
THEN
RAISE EXCEPTION 'source schema % does not exist!', source_schema;
RETURN ;
END IF;
-- Check that dest_schema does not yet exist
PERFORM nspname
FROM pg_namespace
WHERE nspname = dest_schema;
IF FOUND
THEN
RAISE EXCEPTION 'dest schema % already exists!', dest_schema;
RETURN ;
END IF;
EXECUTE 'CREATE SCHEMA "' || dest_schema || '"';
-- Create tables
FOR object IN
SELECT TABLE_NAME::text
FROM information_schema.tables
WHERE table_schema = source_schema
AND table_type = 'BASE TABLE'
LOOP
buffer := '"' || dest_schema || '".' || quote_ident(object);
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE "' || source_schema || '".' || quote_ident(object)
|| ' INCLUDING ALL);';
IF include_recs
THEN
-- Insert records from source table
EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM "' || source_schema || '".' || quote_ident(object) || ';';
END IF;
END LOOP;
-- add FK constraint
FOR qry IN
SELECT 'ALTER TABLE "' || dest_schema || '".' || quote_ident(rn.relname)
|| ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';'
FROM pg_constraint ct
JOIN pg_class rn ON rn.oid = ct.conrelid
WHERE connamespace = src_oid
AND rn.relkind = 'r'
AND ct.contype = 'f'
LOOP
EXECUTE qry;
END LOOP;
-- Create sequences
FOR seq_rec IN
SELECT
s.sequence_name::text,
table_name,
column_name
FROM information_schema.sequences s
JOIN (
SELECT
substring(column_default from E'^nextval\(''(?:[^"'']?.*["'']?\.)?([^'']*)''(?:::text|::regclass)?\)')::text as seq_name,
table_name,
column_name
FROM information_schema.columns
WHERE column_default LIKE 'nextval%'
AND table_schema = source_schema
) c ON c.seq_name = s.sequence_name
WHERE sequence_schema = source_schema
LOOP
seq_buffer := quote_ident(dest_schema) || '.' || quote_ident(seq_rec.sequence_name);
EXECUTE 'CREATE SEQUENCE ' || seq_buffer || ';';
qry := 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
FROM "' || source_schema || '".' || quote_ident(seq_rec.sequence_name) || ';';
EXECUTE qry INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ;
IF sq_is_cycled
THEN
sq_cycled := 'CYCLE';
ELSE
sq_cycled := 'NO CYCLE';
END IF;
EXECUTE 'ALTER SEQUENCE ' || seq_buffer
|| ' INCREMENT BY ' || sq_increment_by
|| ' MINVALUE ' || sq_min_value
|| ' MAXVALUE ' || sq_max_value
|| ' START WITH ' || sq_start_value
|| ' RESTART ' || sq_min_value
|| ' CACHE ' || sq_cache_value
|| ' OWNED BY ' || quote_ident(dest_schema ) || '.'
|| quote_ident(seq_rec.table_name) || '.'
|| quote_ident(seq_rec.column_name) || ' '
|| sq_cycled || ' ;' ;
IF include_recs
THEN
EXECUTE 'SELECT setval( ''' || seq_buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
ELSE
EXECUTE 'SELECT setval( ''' || seq_buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
END IF;
table_buffer := quote_ident(dest_schema) || '.' || quote_ident(seq_rec.table_name);
FOR table_rec IN
SELECT column_name::text AS column_,
REPLACE(column_default::text, source_schema, quote_ident(dest_schema)) AS default_
FROM information_schema.COLUMNS
WHERE table_schema = dest_schema
AND TABLE_NAME = seq_rec.table_name
AND column_default LIKE 'nextval(%' || seq_rec.sequence_name || '%::regclass)'
LOOP
EXECUTE 'ALTER TABLE ' || table_buffer || ' ALTER COLUMN ' || table_rec.column_ || ' SET DEFAULT nextval(' || quote_literal(seq_buffer) || '::regclass);';
END LOOP;
END LOOP;
-- Create views
FOR object IN
SELECT table_name::text,
view_definition
FROM information_schema.views
WHERE table_schema = source_schema
LOOP
buffer := '"' || dest_schema || '".' || quote_ident(object);
SELECT view_definition INTO v_def
FROM information_schema.views
WHERE table_schema = source_schema
AND table_name = quote_ident(object);
EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ;
END LOOP;
-- Create functions
FOR func_oid IN
SELECT oid
FROM pg_proc
WHERE pronamespace = src_oid
LOOP
SELECT pg_get_functiondef(func_oid) INTO qry;
SELECT replace(qry, source_schema, dest_schema) INTO dest_qry;
EXECUTE dest_qry;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
0' from encode(tgargs,'escape')), 'DO LANGUAGE plpgsql
$body$
DECLARE
old_schema NAME = 'src_schema';
new_schema NAME = 'dst_schema';
tbl TEXT;
sql TEXT;
BEGIN
EXECUTE format('CREATE SCHEMA IF NOT EXISTS %I', new_schema);
FOR tbl IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema=old_schema
LOOP
sql := format(
'CREATE TABLE IF NOT EXISTS %I.%I '
'(LIKE %I.%I INCLUDING INDEXES INCLUDING CONSTRAINTS)'
, new_schema, tbl, old_schema, tbl);
EXECUTE sql;
sql := format(
'INSERT INTO %I.%I '
'SELECT * FROM %I.%I'
, new_schema, tbl, old_schema, tbl);
EXECUTE sql;
END LOOP;
END
$body$;
0',','),'{(.+)}','''{}''','g')
|| ')' as action_statement
FROM pg_trigger trg
JOIN pg_class tbl on trg.tgrelid = tbl.oid
JOIN pg_proc pc ON pc.oid = trg.tgfoid
WHERE trg.tgname not like 'RI_ConstraintTrigger%'
AND trg.tgname not like 'pg_sync_pg%'
AND tbl.relnamespace = (SELECT oid FROM pg_namespace where nspname = quote_ident(source_schema) )
LOOP
buffer := dest_schema || '.' || quote_ident(rec.trigger_table);
IF show_details THEN RAISE NOTICE 'Creating trigger % % % ON %...', rec.trigger_name, rec.action_timing, rec.trigger_event, rec.trigger_table; END IF;
EXECUTE 'CREATE TRIGGER ' || rec.trigger_name || ' ' || rec.action_timing
|| ' ' || rec.trigger_event || ' ON ' || buffer || ' FOR EACH '
|| rec.trigger_level || ' ' || replace(rec.action_statement, source_schema_dot, '');
END LOOP;
-- Create views
FOR object IN
SELECT table_name::text,
view_definition
FROM information_schema.views
WHERE table_schema = quote_ident(source_schema)
LOOP
buffer := dest_schema || '.' || quote_ident(object);
SELECT replace(view_definition, source_schema_dot, '') INTO v_def
FROM information_schema.views
WHERE table_schema = quote_ident(source_schema)
AND table_name = quote_ident(object);
IF show_details THEN RAISE NOTICE 'Creating view % AS %', object, regexp_replace(v_def, '[\n\r]+', ' ', 'g'); END IF;
EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
回答by van
- If by copy schemayou mean copy a database, then just use
TEMPLATE
option to create a copy:CREATE DATABASE dbname_target TEMPLATE dbname_source;
- 如果复制架构是指复制数据库,则只需使用
TEMPLATE
选项创建副本:CREATE DATABASE dbname_target TEMPLATE dbname_source;
This will copy data too. So you might want to create your own template if you need many copies. See Template Databases.
这也会复制数据。因此,如果您需要许多副本,您可能想要创建自己的模板。请参阅模板数据库。
- If you need only schema, then I suggest that you put your DB DDL scripts under source control (which is a good idea anyways) and have a separate (templated) script which will create the schema for you. Basically you have one SQL file, where you replace a
${schema_name}
with your new schema name, and then execute this script on the database. In this way if you make a changes to thisschema
, you can also have scripts to update the schema to a new version, which you will have to do for every user schema in this case.
- 如果您只需要架构,那么我建议您将 DB DDL 脚本置于源代码控制之下(无论如何这是一个好主意)并拥有一个单独的(模板化)脚本来为您创建架构。基本上,您有一个 SQL 文件,您可以将其中的 a 替换为
${schema_name}
新的模式名称,然后在数据库上执行此脚本。这样,如果您对此进行更改schema
,您还可以使用脚本将架构更新为新版本,在这种情况下,您必须为每个用户架构执行此操作。
回答by blep
Using @IdanDavidi's solution, I was able to solve the case where sequences were owned by and referring to the source schema instead of the destination schema.
使用@IdanDavidi 的解决方案,我能够解决序列由源模式拥有并引用源模式而不是目标模式的情况。
DO LANGUAGE plpgsql
$body$
DECLARE
old_schema NAME = 'src_schema';
new_schema NAME = 'dst_schema';
tbl TEXT;
sql TEXT;
BEGIN
EXECUTE format('CREATE SCHEMA IF NOT EXISTS %I', new_schema);
FOR tbl IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema=old_schema
LOOP
sql := format(
'CREATE TABLE IF NOT EXISTS %I.%I '
'AS '
'SELECT * FROM %I.%I'
, new_schema, tbl, old_schema, tbl);
raise notice 'Sql: %', sql;
EXECUTE sql;
END LOOP;
END
$body$;
回答by Jozef Cechovsky
You can use this simple script :
您可以使用这个简单的脚本:
SET search_path = source_schema, pg_catalog;
回答by Jozef Cechovsky
In the case you are OK with only tables and columns (without constraints, keys etc.) this simple script could be helpful
如果您只使用表和列(没有约束、键等),这个简单的脚本可能会有所帮助
CREATE SCHEMA new_schema;
SET search_path = new_schema, pg_catalog;
回答by Milan Oparnica
This seems to be the best solution I came up to.
这似乎是我想到的最佳解决方案。
The idea is to use pg_dump with -O (no owner) and -o (oids) options to get plain text output withoutsource schema and owner information.
这个想法是使用带有 -O(无所有者)和 -o(oids)选项的 pg_dump 来获得没有源架构和所有者信息的纯文本输出。
Such output i filter through sedreplacing the default entry
这样的输出我通过sed过滤替换默认条目
pg_dump -U postgres -Oo -n public -d b1 | sed 's/SET search_path = public, pg_catalog;/CREATE SCHEMA "2016";SET search_path = "2016", pg_catalog;/' | psql -U postgres -d b1
with command to create the new schema and set the default search path to it
使用命令创建新模式并为其设置默认搜索路径
##代码##After that I redirect the stream to psqllogging to desired user and database to which copy of the schema will be transfered.
之后,我将流重定向到psql日志记录到所需的用户和数据库,模式的副本将传输到该数据库。
The final command to copy schema 'public' to schema '2016' in the same database 'b1' looks like this:
将模式“public”复制到同一数据库“b1”中的模式“2016”的最终命令如下所示:
##代码##Please note that GRANTS are not transfered from the source schema to the new one.
请注意,GRANTS 不会从源架构转移到新架构。