将SQLITE SQL转储文件转换为POSTGRESQL

时间:2011-01-03 02:33:27

标签: database sqlite postgresql migration

我一直在使用带有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兼容转储文件?

8 个答案:

答案 0 :(得分:88)

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

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

如果希望id列为“自动增量”,则在表创建行中将其类型从“int”更改为“serial”。然后,PostgreSQL会将一个序列附加到该列,以便自动为具有NULL ID的INSERT分配下一个可用值。 PostgreSQL也不会识别AUTOINCREMENT命令,因此需要将其删除。

您还需要检查SQLite架构中的datetime列,并将其更改为timestamp以便PostgreSQL(感谢Clay指出这一点)。

如果您的SQLite中有布尔值,那么您可以转换10以及1::boolean0::boolean(或者分别),或者您可以将布尔列更改为整数在转储的schema部分中,然后在导入后在PostgreSQL中手动修复它们。

如果您的SQLite中有BLOB,那么您需要调整架构以使用bytea。你可能需要混合一些decode calls as well。如果你要处理很多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)
);

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

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

答案 1 :(得分:54)

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

喜欢docs州。然后,我创建了testdb createdb

createdb testdb

我像这样运行pgloader命令:

pgloader command

然后连接到新数据库:

psql testdb

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

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

答案 2 :(得分:15)

我编写了一个脚本来执行sqlite3postgres迁移。它不处理https://stackoverflow.com/a/4581921/1303625中提到的所有模式/数据转换,但它完成了我需要它做的事情。希望这对其他人来说是一个很好的起点。

https://gist.github.com/2253099

答案 3 :(得分:11)

sequel gem(Ruby库)提供跨不同数据库的数据复制: http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases

对于sqlite,它会是这样的: UITableViewCell

答案 4 :(得分: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 

答案 5 :(得分:0)

我已经尝试过对sqlite转储进行编辑/再扩展,以便PostgreSQL接受它,这很乏味并且容易出错。

我必须快速工作:

首先在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)

这就像一个符咒,很容易编写,读取和调试每个函数,与正则表达式不同(对我而言)。

现在,您可以尝试使用PostgreSQL加载生成的csv(甚至使用管理工具以图形方式),唯一的警告是,在使用相应的源密钥加载表之后,必须使用外键加载表。我没有循环依赖的情况,如果是这种情况,我想您可以暂时中止密钥检查。

答案 6 :(得分:0)

尝试这些步骤...

步骤01:将sqlite数据库转储到json

python3 manage.py dumpdata > data.json

第02步:创建表而不进行迁移

python3 manage.py migrate --run-syncdb

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

python3 manage.py shell
from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()

第04步:加载数据

python3 manage.py loaddata data.json

答案 7 :(得分:-1)

pgloader在将sqlite中的数据库转换为postgresql方面发挥了作用。

下面是将本地sqlitedb转换为远程PostgreSQL数据库的示例:

pgloader sqlite.db postgresql:// 用户名密码 @ 主机名 / dbname < / strong>