SQLITE SQLダンプファイルをPOSTGRESQLに変換する


96

私はPOSTGRESQLで本番環境でSQLITEデータベースを使用して開発を行っています。ローカルデータベースを大量のデータで更新しただけで、特定のテーブルを本番データベースに転送する必要があります。

実行sqlite database .dump > /the/path/to/sqlite-dumpfile.sqlに基づいて、SQLITEは次の形式でテーブルダンプを出力します。

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の
チェラルErgünを

回答:


101

あなたはそのダンプファイルを直接にフィードできるはずですpsql

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

あなたがしたい場合はid、「自動インクリメント」に列を、テーブル作成ラインで「シリアル」を「INT」からそのタイプを変更。次に、PostgreSQLはその列にシーケンスをアタッチし、NULL IDを持つINSERTに次の使用可能な値が自動的に割り当てられるようにします。PostgreSQLもAUTOINCREMENTコマンドを認識しないため、これらを削除する必要があります。

またdatetime、SQLiteスキーマの列を確認し、それらをtimestampPostgreSQLに変更することもできます(これを指摘してくれたClayに感謝します)。

SQLiteにブール値がある場合は、1andおよび0and 1::booleanおよび0::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
これはうまくいきます。またdatetime、sqlite カラムを移行する必要がある場合はtimestamp、postgres用に変更する必要があることにも注意します。
クレー

4
変更:私はに走ったよりいくつかの問題BLOBBYTEAstackoverflow.com/questions/3103242用0/1変え、)BOOLEAN(「1」、「0」/に列を、制約を延期DEFERRABLE/ SET CONSTRAINTS ALL DEFERRED)。
ニコラスライリー

1
@NicholasRiley:ありがとうございます。コミュニティウィキはグループでの取り組みになったため、これはあきらめました。フェアフェアです。
muが短すぎる

2
postgreSQLでto_timestamp()を使用して、タイムスタンプをprogreSQLタイムスタンプに変換できます
r03

61

pgloader

SQLiteダンプをPostgreSQLに変換する方法を探しているときに、この投稿を見つけました。この投稿には回答が承認されています(そして、+ 1で良い回答です)が、これを追加することは重要だと思います。

私はここで解決策を検討し始め、より自動化された方法を探していることに気付きました。私はwikiドキュメントを調べました:

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

ドキュメントの状態のように。次に、を作成しtestdbましたcreatedb

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パッケージマネージャを使用してインストールしてください。「コマンド」ファイルの場合、これは拡張子名のない「コマンド」と呼ばれるテキストファイルです(つまり、ファイル名の末尾に.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

12

続編宝石(ルビーライブラリは)異なるデータベース間でデータのコピーを提供しています: http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases

まずRubyをインストールし、次にを実行してgemをインストールしますgem install sequel

sqliteの場合、次のようになります。 sequel -C sqlite://db/production.sqlite3 postgres://user@localhost/db


1
素晴らしいソリューション。をいじるよりもはるかに簡単ですpgloader
michaeldever '26 / 10/26

確かに、pgloaderは乱雑で、GCは巨大なデータベースでクラッシュするようです:github.com/dimitri/pgloader/issues/962
hasufell

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
もう1つのアイテムを追加できますsed -e 's/DATETIME/TIMESTAMP/g'
silpol '17年

sed -e 's/TINYINT(1)/SMALLINT/g' -およびすべてのデータ型の比較については、stackoverflow.com
questions / 1942586 /…を

また、SQLiteでデフォルトで「t」または「f」になるSMALLINTにも問題がありました。明らかにブール値ですが、安全な修正を推奨するのにどちらのdbシステムにも慣れていません。
ラビリンス

1
交換する' | sed -e '; :)
AstraSerg

0

PostgreSQLがそれを受け入れるようにsqliteダンプを編集/正規表現してみましたが、退屈でエラーが発生しやすくなります。

私が本当に速く仕事をしなければならないもの:

まず、PostgreSQLでスキーマをデータなしで再作成します。ダンプを編集するか、ORMを使用している場合は幸運かもしれませんが、両方のバックエンド(sqlalchemy、peeweeなど)と通信します。

次に、パンダを使用してデータを移行します。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)

これはチャームのように機能し、正規表現(私にとって)とは異なり、各関数の書き込み、読み取り、デバッグが簡単です。

これで、結果のcsvをPostgreSQLで(グラフィカルに管理ツールでも)ロードすることができます。対応するソースキーを使用してテーブルをロードした後で、外部キーを使用してテーブルをロードする必要があるという唯一の警告があります。循環依存のケースはありませんでした。そうである場合は、キーのチェックを一時的に中断できます。


-1

pgloaderは、sqlite内のデータベースをpostgresqlに変換する際に不思議に思います。

ローカルsqlitedbをリモートPostgreSQL dbに変換する例を次に示します。

pgloader sqlite.db postgresql:// usernamepassword @ hostname / 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.