web-dev-qa-db-ja.com

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を複製/コピーするにはどうすればよいですか?

20

おそらくファイルを使わずにコマンドラインからそれを行うことができます:

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

これは、スキーマ名である文字列のすべての出現を検索および置換するため、データに影響する可能性があります

21
user1517922

pg_dump を使用して、データなしでスキーマをダンプします。

-s
--schema-only

データではなく、オブジェクト定義(スキーマ)のみをダンプします。

このオプションは--data-onlyの逆です。これは、--section=pre-data --section=post-dataを指定することと似ていますが、歴史的な理由で同一ではありません。

(これを--schemaオプションと混同しないでください。このオプションは、Wordの「スキーマ」を別の意味で使用します。)

データベース内のテーブルのサブセットのみのテーブルデータを除外するには、--exclude-table-dataを参照してください。

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

次に、ダンプ内のスキーマの名前を変更し(検索と置換)、psqlを使用して復元します。

psql $DB -f filename.pgsql

otherスキーマのテーブルを参照する外部キー制約は、同じスキーマを指すようにコピーされます。
sameスキーマ内のテーブルへの参照は、コピーされたスキーマ内のそれぞれのテーブルを指します。

13

パーティーには少し遅れますが、ここにあるSQLはあなたの道に沿ってあなたを助けることができます:

get schema 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を呼び出す必要がなくなります。

4
rabbitt

私は私の問題の解決策を共有しますが、少しの追加で同じでした。スキーマを複製し、新しいデータベースユーザーを作成して、そのユーザーに新しいスキーマ内のすべてのオブジェクトの所有権を割り当てる必要がありました。

次の例では、参照スキーマが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

。スキーマの名前を変更しますref_schematonew_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
Adam

ちょうど同じに遭遇しました。時々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には通常、他の操作が含まれます(たとえば、ソースとターゲットで異なるユーザー名を使用します)。ただし、データがファイルの一部にならないため、はるかに高速になります。

0
Ilya Dorfman