スキーマ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
を複製/コピーするにはどうすればよいですか?
おそらくファイルを使わずにコマンドラインからそれを行うことができます:
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
オプションと混同しないでください。このオプションは、Wordの「スキーマ」を別の意味で使用します。)データベース内のテーブルのサブセットのみのテーブルデータを除外するには、
--exclude-table-data
を参照してください。
pg_dump $DB -p $PORT -n $SCHEMA -s -f filename.pgsql
次に、ダンプ内のスキーマの名前を変更し(検索と置換)、psql
を使用して復元します。
psql $DB -f filename.pgsql
otherスキーマのテーブルを参照する外部キー制約は、同じスキーマを指すようにコピーされます。
sameスキーマ内のテーブルへの参照は、コピーされたスキーマ内のそれぞれのテーブルを指します。
パーティーには少し遅れますが、ここにある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
を呼び出す必要がなくなります。
私は私の問題の解決策を共有しますが、少しの追加で同じでした。スキーマを複製し、新しいデータベースユーザーを作成して、そのユーザーに新しいスキーマ内のすべてのオブジェクトの所有権を割り当てる必要がありました。
次の例では、参照スキーマが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
これが役に立ったと誰かが願っています。
ちょうど同じに遭遇しました。時々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には通常、他の操作が含まれます(たとえば、ソースとターゲットで異なるユーザー名を使用します)。ただし、データがファイルの一部にならないため、はるかに高速になります。