SQLITE SQL 덤프 파일을 POSTGRESQL로 변환


97

저는 POSTGRESQL에서 프로덕션과 함께 SQLITE 데이터베이스를 사용하여 개발을 해왔습니다. 방대한 양의 데이터로 로컬 데이터베이스를 업데이트했으며 특정 테이블을 프로덕션 데이터베이스로 전송해야합니다.

실행을 기반으로 sqlite database .dump > /the/path/to/sqlite-dumpfile.sqlSQLITE는 다음 형식으로 테이블 덤프를 출력합니다.

BEGIN TRANSACTION;
CREATE TABLE "courses_school" ("id" integer PRIMARY KEY, "department_count" integer NOT NULL DEFAULT 0, "the_id" integer UNIQUE, "school_name" varchar(150), "slug" varchar(50));
INSERT INTO "courses_school" VALUES(1,168,213,'TEST Name A',NULL);
INSERT INTO "courses_school" VALUES(2,0,656,'TEST Name B',NULL);
....
COMMIT;

위를 프로덕션 서버로 가져올 수있는 POSTGRESQL 호환 덤프 파일로 어떻게 변환합니까?


1
나는 변경 될 때까지 글쎄, 그 명령은 나를 위해 작동하지 않았다 sqlite가sqlite3를
Celal Ergün을

답변:


102

해당 덤프 파일을 다음 위치에 직접 공급할 수 있어야합니다 psql.

/path/to/psql -d database -U username -W < /the/path/to/sqlite-dumpfile.sql

당신이 원하는 경우 id"자동 증가"에 열을 후 테이블 생성 줄에 "시리얼"에서 "INT"에서 유형을 변경합니다. 그런 다음 PostgreSQL은 해당 열에 시퀀스를 연결하여 NULL ID가있는 INSERT에 다음 사용 가능한 값을 자동으로 할당합니다. PostgreSQL은 AUTOINCREMENT명령을 인식하지 못 하므로 제거해야합니다.

또한 datetimeSQLite 스키마에서 열 을 확인 timestamp하고 PostgreSQL 용으로 변경하고 싶을 것 입니다. ( 이 점을 지적 해 주신 Clay 에게 감사드립니다 .)

당신이 당신의 SQLite는의 논리 값이 있다면 당신은 변환 할 수 101::boolean0::boolean(각각)하거나 덤프의 스키마 섹션에서 정수로 부울 열을 변경 한 다음 가져 오기 후 PostgreSQL의 내부에 손으로 그들을 해결할 수 있습니다.

SQLite에 BLOB가있는 경우를 사용하도록 스키마를 조정하고 싶을 것 bytea입니다. 일부 decode통화도 믹스해야 할 것입니다 . 하지만 처리해야 할 BLOB가 많으면 좋아하는 언어로 빠르고 더러운 복사기를 작성하는 것이 SQL을 조작하는 것보다 쉬울 수 있습니다.

평소처럼 외래 키가있는 경우 set constraints all deferred삽입 순서 문제를 방지하기 위해 BEGIN / COMMIT 쌍 안에 명령을 배치하는 것이 좋습니다.

부울, 블롭 및 제약 사항 메모에 대해 Nicolas Riley 에게 감사드립니다 .

`일부 SQLite3 클라이언트에 의해 생성 된 코드 가있는 경우 이를 제거해야합니다.

PostGRESQL은 또한 unsigned열을 인식하지 않으므로이를 삭제하거나 다음과 같은 사용자 지정 제약 조건을 추가 할 수 있습니다.

CREATE TABLE tablename (
    ...
    unsigned_column_name integer CHECK (unsigned_column_name > 0)
);

SQLite는 기본적으로 null 값 ''을로 설정하지만 PostgreSQL에서는이를로 설정해야합니다 NULL.

SQLite 덤프 파일의 구문은 대부분 PostgreSQL과 호환되므로 몇 가지를 패치하고 psql. SQL INSERT를 통해 많은 양의 데이터를 가져 오는 데는 시간이 걸릴 수 있지만 작동합니다.


4
아니요, 오버 헤드를 피하기 위해 트랜잭션을 유지하려고합니다.
Peter Eisentraut 2011 년

3
이것은 훌륭하게 작동합니다. 또한 sqlite datetime열 을 마이그레이션해야하는 경우 timestamppostgres 로 변경해야합니다 .
Clay는

4
변경 : 더 몇 가지 문제를 나는 우연히 BLOBBYTEA( stackoverflow.com/questions/3103242 )에 대한 0/1을 변경 BOOLEAN하는 열 '0'/ '1'과 (제약 연기 DEFERRABLE/ SET CONSTRAINTS ALL DEFERRED).
Nicholas Riley

1
@NicholasRiley : 감사합니다. 나는 이것이 그룹 노력으로 바뀌었기 때문에 커뮤니티 위키에 포기했습니다.
뮤 너무 짧은

2
postgreSQL에서 to_timestamp ()를 사용하여 타임 스탬프를 progreSQL 타임 스탬프로 변환 할 수 있습니다
r03

62

pgloader

SQLite 덤프를 PostgreSQL로 변환하는 방법을 찾을 때이 게시물을 보았습니다. 이 게시물에 허용 된 답변 (그리고 해당 +1에서 좋은 답변)이 있지만 추가하는 것이 중요하다고 생각합니다.

여기서 솔루션을 찾기 시작했고 더 자동화 된 방법을 찾고 있다는 것을 깨달았습니다. 위키 문서를 찾았습니다.

https://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL

그리고 발견 pgloader. 매우 멋진 응용 프로그램이며 비교적 사용하기 쉽습니다. 플랫 SQLite 파일을 사용 가능한 PostgreSQL 데이터베이스로 변환 할 수 있습니다. 에서 설치 하고 테스트 디렉토리에 다음과 같은 파일을 *.deb만들었습니다 command.

load database  
    from 'db.sqlite3'  
    into postgresql:///testdb 
       
with include drop, create tables, create indexes, reset sequences  
         
set work_mem to '16MB', maintenance_work_mem to '512 MB';

문서 상태 처럼 . 그런 다음 다음 testdbcreatedb같이 만들었습니다 .

createdb testdb

다음 pgloader과 같은 명령을 실행했습니다 .

pgloader command

그런 다음 새 데이터베이스에 연결됩니다.

psql testdb

데이터를 확인하기 위해 몇 가지 쿼리를 수행 한 후 꽤 잘 작동하는 것으로 보입니다. 이 스크립트 중 하나를 실행하거나 여기에 언급 된 단계적 변환을 시도했다면 훨씬 더 많은 시간을 보냈을 것입니다.

개념을 증명하기 위해 나는 이것을 버리고 testdb프로덕션 서버의 개발 환경으로 가져오고 데이터를 멋지게 전송했습니다.


2
(여전히 지원되는) Ubuntu 배포판에는 오래된 버전이있을 수 있습니다. v2.xy는 이미 더 이상 사용되지 않으며 실제로 작동하지 않습니다. v3.2.x가 작동 할 수 있지만 v3.2.3이 권장됩니다. 나는 블리딩 엣지에서 v3.2.3을 가져 와서 sudo dpkg -i <.deb file name>으로 설치 했으며 종속성에 문제가 없었습니다.
silpol

@silpol과 동의합니다. 안정적인 최신 릴리스를 다운로드하고 fav 패키지 관리자를 사용하여 설치하십시오. "command"파일의 경우 확장자 이름이없는 'command'라는 텍스트 파일입니다 (즉, 파일 이름 끝에 .txt가 필요하지 않음). 파일 이름을 각괄호 안에 넣을 필요가 없습니다. 내 데이터를보기 위해 psql 데이터베이스의 search_parth를 변경해야했습니다. pgloader 잘 작동하고 나에게 번거 로움의 많은 저장
BKSpurgeon

이것은 내 하루를 구합니다.
Yakob Ubaidi 2017

1
예,이 문제가 발생했을 때 어려움을 겪고 있었는데 그 도구로 쉽게 처리 할 수 ​​있습니다 ... 가끔 일이 잘 풀리지 않습니까?
nicorellius

감사합니다 형제. 나는이 대답이 받아 들여질 가치가 있다고 본다! 아주 좋은 도구입니다.
mohamed_18

16

내가 할 수있는 스크립트 작성 sqlite3postgres마이그레이션. https://stackoverflow.com/a/4581921/1303625에 언급 된 모든 스키마 / 데이터 번역을 처리하지는 않지만 필요한 작업을 수행합니다. 다른 사람들에게 좋은 출발점이되기를 바랍니다.

https://gist.github.com/2253099


2
이것은 잘 작동합니다! 나는 요점을 포크하고 주석으로 몇 가지 통찰력을 추가했습니다 : gist.github.com/bittner/7368128
Peterino

14

속편 보석 (루비 라이브러리) 다른 데이터베이스에서 복사 된 데이터를 제공 http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases

먼저 Ruby를 설치 한 다음 gem install sequel.

sqlite의 경우 다음과 같습니다. sequel -C sqlite://db/production.sqlite3 postgres://user@localhost/db


1
멋진 솔루션입니다. 주변에 바이올린을 켜는 것보다 훨씬 쉽다 pgloader.
michaeldever

물론, pgloader는 지저분합니다. GC는 거대한 데이터베이스에서 충돌하는 것 같습니다. github.com/dimitri/pgloader/issues/962
hasufell

stackoverflow.com/questions/6148421/…에 자유롭게 답변을 게시하십시오. 여기에 답변을 복사했습니다. 그런 다음 저에게 핑을 보내면 반복 횟수를 원하면 내 답변을 취소합니다.
Felix

@Felix 감사합니다! 크레딧을받을 수 있습니다. (PG를 SQLite로 원하기 때문에) DB 참조의 순서를 바꾸고 내 ID에 "la"를 하나 더 추가 할 수 있습니다. 답변은 개발자 컴퓨터에 PG를 설치해야하고 그 시점에서 개발을 위해 PG를 사용하기 때문에 덜 도움이 될 수 있습니다.
lulalala

@lulalala 감사합니다. 그거 했어. 그러나 추론에 대해서는 동의하지 않습니다. 예를 들어 리눅스 머신에서 db를 변환 한 다음 dev 머신에 복사 할 수 있습니다 (sqlite db 파일로). 그러나 어쨌든 모두 그것의 나쁜 생각 :) 그러나 속편은 불쾌한 상황에서 여기 내 엉덩이를 구했습니다.
Felix

7

하나의 라이너를 사용할 수 있습니다. 다음은 sed 명령을 사용한 예입니다.

sqlite3 mjsqlite.db .dump | sed -e 's/INTEGER PRIMARY KEY AUTOINCREMENT/SERIAL PRIMARY KEY/' | sed -e 's/PRAGMA foreign_keys=OFF;//' | sed -e 's/unsigned big int/BIGINT/g' | sed -e 's/UNSIGNED BIG INT/BIGINT/g' | sed -e 's/BIG INT/BIGINT/g' | sed -e 's/UNSIGNED INT(10)/BIGINT/' | sed -e 's/BOOLEAN/SMALLINT/g' | sed -e 's/boolean/SMALLINT/g' | sed -e 's/UNSIGNED BIG INT/INTEGER/g' | sed -e 's/INT(3)/INT2/g' | sed -e 's/DATETIME/TIMESTAMP/g' | psql mypqdb mypguser 

어떤이 LONG 유형, 예에 대한 대체하지 않습니다
yetanothercoder

1
또 하나 개의 항목을 추가 할 수 있습니다sed -e 's/DATETIME/TIMESTAMP/g'
silpol

sed -e 's/TINYINT(1)/SMALLINT/g' - 모든 비교에 대한 데이터 유형은 참조 stackoverflow.com/questions/1942586/...
Purplejacket

또한 sqlite에서 't'또는 'f'로 기본 설정된 SMALLINT에 문제가 있습니다. 분명히 부울이지만 안전한 수정을 권장하기 위해 어느 db 시스템에도 익숙하지 않습니다.
미로

1
교체 ' | sed -e '와 함께 ; :)
AstraSerg

0

나는 sqlite 덤프를 편집 / 정규화하여 PostgreSQL이 그것을 받아들이고 지루하고 오류가 발생하기 쉽습니다.

정말 빨리 일하게 된 것 :

먼저 데이터없이 PostgreSQL에서 스키마를 다시 생성합니다. 덤프를 편집하거나 ORM을 사용하는 경우 운이 좋을 수 있으며 두 백엔드 (sqlalchemy, peewee, ...)와 통신합니다.

그런 다음 Pandas를 사용하여 데이터를 마이그레이션합니다. bool 필드가있는 테이블이 있다고 가정합니다 (sqlite에서는 0/1이지만 PostgreSQL에서는 t / f 여야 함).

def int_to_strbool(df, column):
    df = df.replace({column: 0}, 'f')
    df = df.replace({column: 1}, 't')
    return df

#def other_transform(df, column):
#...

conn = sqlite3.connect(db)
df = pd.read_sql(f'select * from {table_name}', conn)

df = int_to_strbool(df, bool_column_name)
#df = other_transform(df, other_column_name)

df.to_csv(table_name + '.csv'), sep=',', header=False, index=False)

이것은 매력처럼 작동하며 정규 표현식과 달리 각 함수를 작성하고 읽고 디버그하기 쉽습니다.

이제 PostgreSQL을 사용하여 결과 csv를로드 할 수 있습니다 (관리 도구를 사용하여 그래픽으로도). 순환 종속성의 경우가 없었습니다. 그렇다면 일시적으로 키 확인을 중단 할 수 있습니다.


-2

pgloader 작업은 sqlite의 데이터베이스를 postgresql로 변환하는 데 놀라운 일입니다.

다음은 로컬 sqlitedb를 원격 PostgreSQL db로 변환하는 예입니다.

pgloader sqlite.db postgresql : // 사용자 이름 : 암호 @ 호스트 이름 / dbname


1
Pgloader는 매우 버그가 많고 신뢰할 수 없습니다. 그것은 즉시 오류와 충돌KABOOM! Control stack exhausted (no more space for function call frames).
Cerin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.