Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to duplicate schemas in PostgreSQL

I have a database with schema public and schema_A. I need to create a new schema schema_b with the same structure than schema_a. I found the function below, the problem is that it does not copy the foreign key constraints.

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

How can I clone/copy schema_A with the foreign key constraints?

like image 535
Cristhian Boujon Avatar asked Aug 13 '13 18:08

Cristhian Boujon


People also ask

How do I create a schema in PostgreSQL?

PostgreSQL has a CREATE SCHEMA statement that is used to create a new schema in a database. Syntax: CREATE SCHEMA [IF NOT EXISTS] schema_name; Let's analyze the above syntax: First, specify the name of the schema after the CREATE SCHEMA keywords.


3 Answers

You can probably do it from the command line without using files:

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

Note that this searches and replaces all occurrences of the string that is your schema name, so it may affect your data.

like image 60
user1517922 Avatar answered Oct 07 '22 14:10

user1517922


I would use pg_dump to dump the schema without data:

-s
--schema-only

Dump only the object definitions (schema), not data.

This option is the inverse of --data-only. It is similar to, but for historical reasons not identical to, specifying --section=pre-data --section=post-data.

(Do not confuse this with the --schema option, which uses the word "schema" in a different meaning.)

To exclude table data for only a subset of tables in the database, see --exclude-table-data.

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

Then rename the schema in the dump (search & replace) and restore it with psql.

psql $DB -f filename.pgsql

Foreign key constraints referencing tables in other schemas are copied to point to the same schema.
References to tables within the same schema point to the respective tables within the copied schema.

like image 21
Erwin Brandstetter Avatar answered Oct 07 '22 15:10

Erwin Brandstetter


I will share a solution for my problem which was the same with a small addition. I needed to clone a schema, create a new database user and assign ownership of all objects in the new schema to that user.

For the following example let's assume that the reference schema is called ref_schema and the target schema new_schema. The reference schema and all the objects within are owned by a user called ref_user.

1. dump the reference schema with pg_dump:

pg_dump -n ref_schema -f dump.sql database_name

2. create a new database user with the name new_user:

CREATE USER new_user

3. rename the schema ref_schema to new_schema:

ALTER SCHEMA ref_schema RENAME TO new_schema

4. change ownership of all objects in the renamed schema to the new user

REASSIGN OWNED BY ref_user TO new_user

5. restore the original reference schema from the dump

psql -f dump.sql database_name

I hope someone finds this helpful.

like image 9
Adam Avatar answered Oct 07 '22 16:10

Adam