13

스키마가 public이고 schema_A 인 데이터베이스가 있습니다. schema_a과 같은 구조로 새 스키마 schema_b을 만들어야합니다. 아래 함수를 찾았습니다. 문제는 외래 키 제약 조건을 복사하지 않는다는 것입니다.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 

방법은 /는 외래 키 제약 schema_A 복사 복제 할 수 있습니다?

+0

SQL 쿼리를 사용하여 스키마를 복제하려면 [this] (https://stackoverflow.com/questions/2370614/copy-schema-and-create-new-schema-with-different-name- in-the-same-data-base/48732283 # 48732283) 답변. – IdanDavidi

답변

18
당신은 사용하여 파일없이 명령 줄에서 그것을 할 아마 수

이 검색 및 스키마 이름 문자열의 모든 항목을 대체, 그래서 이 영향을 미칠 수 있음을

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

귀하의 데이터.

9

나는 데이터없이 스키마를 덤프 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 

그런 다음 덤프의 스키마 이름을 변경 (검색 & 대체) 및 psql로 복원합니다. 다른 스키마에

psql $DB -f filename.pgsql 

외래 키 제약 참조 테이블은 동일한 스키마를 가리 키도록 복사됩니다.
동일 테이블 내의 테이블에 대한 참조는 복사 된 스키마 내의 해당 테이블을 가리 킵니 다. 스키마.

+0

네, 고마워요! 하지만 파일 작업을 피하고 싶었습니다. 나는 그것을 할 수있는 빠른 방법을 찾고있다. –

3

파티하지만, 여기에 몇 가지 SQL이 당신의 길을 따라 당신을 도울 수에 조금 늦게 :

스키마 가져 오기 OID :

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

GET 테이블의 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 시스템 테이블에 대한 유용한 리소스는 here입니다. 또한 내부 쿼리에 대한 자세한 내용을 보려면 pg_dumpsource code을보고 덤프 정보를 수집합니다. 이 경우, 당신은 여전히 ​​문의 소택지을 정렬해야합니다

$ 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 모든 데이터가과 같이, 그 위에 strace을 사용하는 것입니다 수집 방식을 볼 수 있습니다 프로그래밍 방식으로 복제 도구를 함께 구성하고 셸로 이동하여 pg_dump을 호출하지 않아도됩니다.

+1

다음은 pg_dump에 모든 SQL을 사용하고 포탈을 사용하지 않고 스키마 복제 (데이터 복사 포함)를 수행하기 위해 작성한 파이썬 클래스입니다. [https://gist.github.com/rabbitt/97f2c048d9e38c16ce62](https://gist .github.com/rabbitt/97f2c048d9e38c16ce62) – rabbitt