将SQLITE SQL转储文件转换为POSTGRESQL

Dev*_*evX 86 database migration sqlite postgresql

我一直在使用SQLITE数据库进行开发,并在POSTGRESQL中生成.我刚用大量数据更新了我的本地数据库,需要将特定的表传输到生产数据库.

基于运行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;
Run Code Online (Sandbox Code Playgroud)

如何将上述内容转换为可以导入生产服务器的POSTGRESQL兼容转储文件?

mu *_*ort 91

您应该能够将该转储文件直接输入psql:

/path/to/psql -d database -U username -W < /the/path/to/sqlite-dumpfile.sql
Run Code Online (Sandbox Code Playgroud)

如果希望id列"自动增量",则在表创建行中将其类型从"int"更改为"serial".然后,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的布尔,blob和约束音符.

如果您拥有`某些SQLite3客户端生成的代码,则需要将其删除.

PostGRESQL也无法识别unsigned列,您可能希望删除它,或添加自定义约束,例如:

CREATE TABLE tablename (
    ...
    unsigned_column_name integer CHECK (unsigned_column_name > 0)
);
Run Code Online (Sandbox Code Playgroud)

虽然SQLite默认为null值'',但PostgreSQL要求将它们设置为NULL.

SQLite转储文件中的语法似乎与PostgreSQL大多兼容,因此您可以修补一些内容并将其提供给psql.通过SQL INSERT导入大量数据可能需要一段时间,但它会起作用.

  • 不,您希望保持交易以避免一些开销. (4认同)
  • 我遇到了一些问题:将`BLOB`改为`BYTEA`(http://stackoverflow.com/questions/3103242/),将`1 BOOLEAN`列改为0/1,改为'0'/'1',推迟约束(`DEFERRABLE` /`SET CONSTRAINTS ALL DEFERRED`). (4认同)
  • 这非常有效.我还要注意,如果你需要迁移sqlite`datetime`列,你必须将它们更改为postgres的`timestamp`. (3认同)
  • @NicholasRiley:谢谢。我把它交给了一个社区维基,因为它已经变成了一个团队的努力,公平就是公平。 (2认同)
  • 您可以使用postgreSQL中的to_timestamp()将时间戳转换为progreSQL时间戳 (2认同)
  • “你应该能够将该转储文件直接输入到 psql 中”这根本不起作用。转储的 sqlite sql 文件需要进行重大转换,您的评论提到了这一点,但没有完全解释。您是否期望 OP 手动编辑千兆字节大小的 sql 文件? (2认同)

nic*_*ius 56

pgloader

在搜索将SQLite转储转换为PostgreSQL的方法时,我遇到了这篇文章.即使这篇文章有一个已接受的答案(并且在+1上有一个好的答案),我认为添加这个很重要.

我开始在这里研究解决方案,并意识到我正在寻找一种更自动化的方法.我查了维基文档:

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

并发现pgloader.非常酷的应用程序,它相对容易使用.您可以将平面SQLite文件转换为可用的PostgreSQL数据库.我从中安装*.debcommand在测试目录中创建了这样的文件:

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';
Run Code Online (Sandbox Code Playgroud)

喜欢文档状态.然后我创建了一个testdb具有createdb:

createdb testdb

pgloader像这样运行命令:

pgloader command

然后连接到新数据库:

psql testdb

经过一些查询检查数据后,它看起来效果很好.我知道如果我试图运行其中一个脚本或执行此处提到的逐步转换,我会花更多的时间.

为了证明这个概念,我将其转储testdb并导入到生产服务器上的开发环境中,并且数据传输得很好.

  • 请注意(仍受支持)Ubuntu 发行版可能已过时版本 - v2.xy 已被弃用并且实际上不起作用。v3.2.x 可能有效,但建议使用 v3.2.3。我已经从前沿获取 v3.2.3 并安装了 _sudo dpkg -i &lt;.deb 文件名&gt;_,它在依赖项方面没有问题。 (2认同)

小智 15

我写了一个脚本来sqlite3进行postgres迁移.它不处理/sf/answers/320734501/中提到的所有模式/数据转换,但它完成了我需要它做的事情.希望这对其他人来说是一个很好的起点.

https://gist.github.com/2253099

  • 这很好用!我已经分享了Gist并添加了一些见解作为评论:https://gist.github.com/bittner/7368128 (2认同)

lul*_*ala 12

续集宝石(一个Ruby库)在不同的数据库提供数据复制: http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases

在sqlite的情况下,它将是这样的: gem install sequel

  • 很棒的解决方案。比摆弄“pgloader”容易得多。 (4认同)
  • 当然,pgloader 很混乱,GC 似乎在巨大的数据库上崩溃:https://github.com/dimitri/pgloader/issues/962 (2认同)

dev*_*Cuy 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 
Run Code Online (Sandbox Code Playgroud)

  • 还可以添加一项 `sed -e 's/DATETIME/TIMESTAMP/g'` (2认同)
  • 替换`' | sed -e '` 与 `; `:) (2认同)

小智 5

尝试这些步骤...

步骤01:将sqlite db转储到json

python3 manage.py dumpdata > data.json
Run Code Online (Sandbox Code Playgroud)

步骤02:创建不迁移的表

python3 manage.py migrate --run-syncdb
Run Code Online (Sandbox Code Playgroud)

步骤03:打开django shell。然后排除内容类型数据

python3 manage.py shell
from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()
Run Code Online (Sandbox Code Playgroud)

步骤04:加载数据

python3 manage.py loaddata data.json
Run Code Online (Sandbox Code Playgroud)