13

Mam bazę danych ze schematem public i schema_A. Muszę utworzyć nowy schemat schema_b o tej samej strukturze co schema_a. Znalazłem funkcję poniżej, problem polega na tym, że nie kopiuje ograniczeń klucza obcego.Jak duplikować schematy w PostgreSQL

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 

Jak można sklonować/skopiować schema_A z zagranicznymi kluczowych ograniczeń?

+0

Jeśli chcesz sklonować schemat za pomocą zapytania SQL, sprawdź [to] (https://stackoverflow.com/questions/2370614/copy-schema-and-create-new-schema-with-different-name- w tej samej bazie danych/48732283 # 48732283). – IdanDavidi

Odpowiedz

18

Prawdopodobnie można to zrobić z wiersza polecenia bez używania plików:

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

Note że ten wyszukiwania i zastępuje wszystkie wystąpienia ciągu znaków, który jest twoja nazwa schematu, więc może wpływać twoje dane.

9

użyłbym pg_dump zrzucić schematu bez danych:

-s 
--schema-only 

Dump tylko definicje obiektów (schematu), brak danych. Ta opcja jest odwrotna do --data-only. Jest podobny do, ale z przyczyn historycznych nie jest identyczny z określeniem --section=pre-data --section=post-data.

(Nie mylić z opcją --schema, który używa słowa „schematu” w innym znaczeniu.)

Aby wykluczyć dane z tabeli tylko podzbioru tabel w bazie danych, patrz --exclude-table-data.

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

następnie zmień nazwę schematu na wysypisko (search & zastąpić) i przywrócić go z psql.

psql $DB -f filename.pgsql 

klucz obcy ograniczenia stoły odniesienie w innych schematów są kopiowane do punktu do tego samego schematu.
Odwołania do tabel w ramach schematu o tym samym wskazują odpowiednie tabele w skopiowanym schemacie.

+0

Tak, dziękuję! ale chciałem uniknąć pracy z plikami. Szukam szybkiego sposobu na zrobienie tego. –

3

Trochę późno do partii, ale niektóre sql tutaj może pomóc po drodze:

schematu get oid: oid

namespace_id = SELECT oid 
        FROM pg_namespace 
       WHERE nspname = '<schema name>'; 

dostać stołu:

table_id = SELECT relfilenode 
       FROM pg_class 
       WHERE relnamespace = '<namespace_id>' AND relname = '<table_name>' 

Uzyskaj ograniczenia klucza obcego:

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'; 

Dobrym źródłem informacji dla tabel systemowych PostgreSQL można znaleźć here. Ponadto możesz dowiedzieć się więcej na temat wewnętrznych zapytań, aby uzyskać informacje o zrzutach, wyświetlając ich numer source code.

Prawdopodobnie najprostszym sposobem, aby zobaczyć, jak pg_dump gromadzi wszystkie dane byłoby użyć strace na nim tak:

$ strace -f -e sendto -s8192 -o pg_dump.trace pg_dump -s -n <schema> 
$ grep -oP '(SET|SELECT)\s.+(?=\\0)' pg_dump.trace 

wciąż masz do sortowania bagna sprawozdania, ale powinno pomóc programistycznie skleić narzędzie do klonowania i uniknąć konieczności wpadania do powłoki, aby wywołać pg_dump.

+1

Oto klasa Pythona, którą właśnie napisałem, aby wykonać klon schematu (łącznie z kopiowaniem danych) przy użyciu wszystkich SQL i bez łuskania na pg_dump: [https://gist.github.com/rabbitt/97f2c048d9e38c16ce62](https://gist .github.com/rabbitt/97f2c048d9e38c16ce62) – rabbitt