在 sql 不工作的情况下复制 postgres 上的模式
Copy schema on postgres with sql not working
我在 postgres 上有多租户应用程序,为了创建帐户,我复制了一个模式 "template" 并为帐户数据重命名它。
我使用 "sql" 变量来复制模式“_template”。
当我执行此操作时,一切正常,但具有 DEFAULT 属性的列未被替换。
但是当直接在 pgAdmin 中执行时 sql 工作正常。
示例:
"id bigint NOT NULL DEFAULT nextval('_template.table_id_seq'::regclass)"
这个 _template.table_id_seq... 应该是 [schemaname].table_id_seq
String sql = new String(
"DO " +
"$do$ " +
"DECLARE " +
" objeto text; " +
" buffer text; " +
" source_schema text; " +
" dest_schema text; " +
" default_ text; " +
" column_ text; " +
"BEGIN " +
" " +
" source_schema := '_template'; " +
" dest_schema := '" + schema + "'; " +
" " +
"EXECUTE 'CREATE SCHEMA ' || dest_schema ; " +
" " +
" FOR objeto IN " +
" SELECT sequence_name::text FROM information_schema.SEQUENCES WHERE sequence_schema = source_schema " +
" LOOP " +
"EXECUTE 'CREATE SEQUENCE ' || dest_schema || '.' || objeto; " +
" END LOOP; " +
" " +
" " +
" FOR objeto IN " +
" SELECT table_name::text FROM information_schema.TABLES WHERE table_schema = source_schema " +
" LOOP " +
" buffer := dest_schema || '.' || objeto; " +
" EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || source_schema || '.' || objeto || ' 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 = source_schema AND table_name = objeto AND column_default LIKE 'nextval(%' || source_schema || '%)' " +
" LOOP " +
"EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_; " +
" END LOOP; " +
" " +
" END LOOP; " +
"END " +
"$do$ "
);
这里是一个 sql var 输出的例子
DO $do$
DECLARE
objeto text;
buffer text;
source_schema text;
dest_schema text;
default_ text;
column_ text;
BEGIN
source_schema := '_template';
dest_schema := 'schemacopied';
EXECUTE 'CREATE SCHEMA ' || dest_schema ;
FOR objeto IN
SELECT sequence_name::text FROM information_schema.SEQUENCES WHERE sequence_schema = source_schema
LOOP
EXECUTE 'CREATE SEQUENCE ' || dest_schema || '.' || objeto;
END LOOP;
FOR objeto IN
SELECT table_name::text FROM information_schema.TABLES WHERE table_schema = source_schema
LOOP
buffer := dest_schema || '.' || objeto;
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || source_schema || '.' || objeto || ' 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 = objeto AND column_default LIKE 'nextval(%' || source_schema || '%)'
LOOP
EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
END LOOP;
END LOOP;
END $do$
information_schema.COLUMNS.column_default
中引用的 nextval(...)
表达式是动态生成的,以根据当前 search_path
.
包含或排除架构名称
如果序列的架构不在 search path
中,则该架构显示为序列名称的前缀,否则不会。
因此这个子句的结果,真假:
column_default LIKE 'nextval(%' || source_schema || '%)'
确实取决于 search_path
,这可以解释为什么它在某些情况下(您在 pgAdmin 中的测试)有效,而在其他情况下无效。
为了不依赖它,您可以在阻止期间强制 search_path
,如:
DO $$
BEGIN
SET LOCAL search_path TO public;
...
...
END
$$ LANGUAGE plpgsql;
或者您可以将 search_path
设置为源架构,在这种情况下,这些与架构相关的 default
可能根本不需要任何 post 处理条款。
我在 postgres 上有多租户应用程序,为了创建帐户,我复制了一个模式 "template" 并为帐户数据重命名它。
我使用 "sql" 变量来复制模式“_template”。 当我执行此操作时,一切正常,但具有 DEFAULT 属性的列未被替换。 但是当直接在 pgAdmin 中执行时 sql 工作正常。
示例: "id bigint NOT NULL DEFAULT nextval('_template.table_id_seq'::regclass)" 这个 _template.table_id_seq... 应该是 [schemaname].table_id_seq
String sql = new String(
"DO " +
"$do$ " +
"DECLARE " +
" objeto text; " +
" buffer text; " +
" source_schema text; " +
" dest_schema text; " +
" default_ text; " +
" column_ text; " +
"BEGIN " +
" " +
" source_schema := '_template'; " +
" dest_schema := '" + schema + "'; " +
" " +
"EXECUTE 'CREATE SCHEMA ' || dest_schema ; " +
" " +
" FOR objeto IN " +
" SELECT sequence_name::text FROM information_schema.SEQUENCES WHERE sequence_schema = source_schema " +
" LOOP " +
"EXECUTE 'CREATE SEQUENCE ' || dest_schema || '.' || objeto; " +
" END LOOP; " +
" " +
" " +
" FOR objeto IN " +
" SELECT table_name::text FROM information_schema.TABLES WHERE table_schema = source_schema " +
" LOOP " +
" buffer := dest_schema || '.' || objeto; " +
" EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || source_schema || '.' || objeto || ' 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 = source_schema AND table_name = objeto AND column_default LIKE 'nextval(%' || source_schema || '%)' " +
" LOOP " +
"EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_; " +
" END LOOP; " +
" " +
" END LOOP; " +
"END " +
"$do$ "
);
这里是一个 sql var 输出的例子
DO $do$
DECLARE
objeto text;
buffer text;
source_schema text;
dest_schema text;
default_ text;
column_ text;
BEGIN
source_schema := '_template';
dest_schema := 'schemacopied';
EXECUTE 'CREATE SCHEMA ' || dest_schema ;
FOR objeto IN
SELECT sequence_name::text FROM information_schema.SEQUENCES WHERE sequence_schema = source_schema
LOOP
EXECUTE 'CREATE SEQUENCE ' || dest_schema || '.' || objeto;
END LOOP;
FOR objeto IN
SELECT table_name::text FROM information_schema.TABLES WHERE table_schema = source_schema
LOOP
buffer := dest_schema || '.' || objeto;
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || source_schema || '.' || objeto || ' 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 = objeto AND column_default LIKE 'nextval(%' || source_schema || '%)'
LOOP
EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
END LOOP;
END LOOP;
END $do$
information_schema.COLUMNS.column_default
中引用的 nextval(...)
表达式是动态生成的,以根据当前 search_path
.
如果序列的架构不在 search path
中,则该架构显示为序列名称的前缀,否则不会。
因此这个子句的结果,真假:
column_default LIKE 'nextval(%' || source_schema || '%)'
确实取决于 search_path
,这可以解释为什么它在某些情况下(您在 pgAdmin 中的测试)有效,而在其他情况下无效。
为了不依赖它,您可以在阻止期间强制 search_path
,如:
DO $$
BEGIN
SET LOCAL search_path TO public;
...
...
END
$$ LANGUAGE plpgsql;
或者您可以将 search_path
设置为源架构,在这种情况下,这些与架构相关的 default
可能根本不需要任何 post 处理条款。