Как дублировать схемы в PostgreSQL

у меня есть база данных со схемой 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 С ограничениями внешнего ключа?

4 ответов


вероятно, вы можете сделать это из командной строки без использования файлов:

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

Примечание что это ищет и заменяет все вхождения строки, которая является вашим именем схемы, так что это может повлиять на ваши данные.


Я хотел бы использовать 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

затем переименуйте схему в дампе (search & replace) и восстановите ее с помощью psql.

psql $DB -f filename.pgsql

ограничения внешнего ключа ссылки на таблицы в другое схемы копируются, чтобы указать на ту же схему.
Ссылки на таблицы в то же самое схема указывает на соответствующие таблицы в скопированной схеме.


немного поздно на вечеринку, но некоторые 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

вам все равно придется сортировать болото операторов, но это должно помочь вам собрать инструмент клонирования программно и избежать падения в оболочку для вызова pg_dump.


я поделюсь решением моей проблемы, которое было таким же с небольшим добавлением. Мне нужно было клонировать схему, создать нового пользователя базы данных и назначить этому пользователю право собственности на все объекты в новой схеме.

в следующем примере Предположим, что ссылочная схема называется 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 to 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

надеюсь, кто-то найдет это полезным.