如何将SQLite SQL转储文件转换为PostgreSQL?

i34xakig  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(8)|浏览(313)

对于开发,我在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兼容的转储文件,我可以导入到生产服务器中?

7hiiyaii

7hiiyaii1#

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

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

如果您希望id列为“auto increase”,那么在表创建行中将其类型从“int”更改为“serial”。PostgreSQL会给这个列附加一个序列,这样带有NULL id的INSERT会被自动分配下一个可用的值。PostgreSQL也不会识别AUTOINCREMENT命令,因此需要删除这些命令。
您还需要检查SQLite模式中的datetime列,并将其更改为PostgreSQL的timestamp。(感谢Clay指出这一点。
如果你的SQLite中有布尔值,那么你可以将10分别转换为1::boolean0::boolean,或者你可以在转储的schema部分将布尔列改为整数,然后在导入后在PostgreSQL中手动修复它们。
如果您的SQLite中有BLOB,那么您需要调整模式以使用bytea。您可能需要混合一些decode calls as well。如果你有很多BLOB要处理的话,用你最喜欢的语言编写一个快速的“n”脏的复制器可能比修改SQL容易。
通常,如果您有外键,那么您可能需要查看set constraints all deferred以避免插入顺序问题,将命令放在开始/COMMIT对中。
感谢Nicolas Riley中的布尔值、blob和约束注解。
如果您的代码中有```(由某些SQLite3客户端生成),则需要删除它们。
PostGRESQL也不识别unsigned列,所以你可能需要删除它或添加一个自定义的约束,例如:

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

虽然SQLite默认null值为'',但是PostgreSQL要求它们设置为NULL
SQLite转储文件中的语法似乎与PostgreSQL基本兼容,因此您可以修补一些内容并将其提供给psql。通过SQL INSERT导入一大堆数据可能需要一段时间,但它会工作。

pbwdgjma

pbwdgjma2#

pgloader

我在寻找将SQLite转储转换为PostgreSQL的方法时偶然发现了这篇文章。尽管这篇文章有一个被接受的答案(而且是一个很好的+1),我认为添加这一点很重要。
我开始研究这里的解决方案,并意识到我正在寻找一种更自动化的方法。我查了一下wiki文档:
https://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL
发现了pgloader相当酷的应用程序,它相对容易使用。您可以将平面SQLite文件转换为可用的PostgreSQL数据库。我从*.deb安装,并在test目录中创建了一个如下所示的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';

就像医生说的那样。然后我用createdb创建了一个testdb
createdb testdb
我运行pgloader命令如下:
pgloader command
然后连接到新的数据库:
psql testdb
经过一些查询以检查数据,它似乎工作得相当好。我知道如果我尝试运行这些脚本中的一个或执行这里提到的逐步转换,我会花费更多的时间。
为了证明这个概念,我丢弃了这个testdb,并导入到生产服务器上的开发环境中,数据传输得很好。

8aqjt8rx

8aqjt8rx3#

sequel gem(一个Ruby库)提供跨不同数据库的数据复制:http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases
首先安装Ruby,然后通过运行gem install sequel安装gem。
在sqlite的情况下,它会像这样:sequel -C sqlite://db/production.sqlite3 postgres://user@localhost/db

yh2wf1be

yh2wf1be4#

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

zd287kbt

zd287kbt5#

你可以使用一行代码,这里是一个在sed命令帮助下的例子:

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

dwthyt8l6#

试试这些步骤…
步骤01:转储sqlite db到json

python3 manage.py dumpdata > data.json

步骤02:创建表而不迁移

python3 manage.py migrate --run-syncdb

步骤03:打开django shell。然后排除contentType数据

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

步骤04:加载数据

python3 manage.py loaddata data.json
dbf7pr2w

dbf7pr2w7#

pgloader在将sqlite中的数据库转换为postgresql上创造了奇迹。
下面是一个将本地sqlitedb转换为远程PostgreSQL db的示例:
pgloadersqlite.dbpostgresql://usernamepassword@hostname/dbname

q3aa0525

q3aa05258#

我试过编辑/regexping sqlite转储,以便PostgreSQL接受它,这是繁琐的,容易出错。
我的工作非常快:
首先在PostgreSQL上不带任何数据地重新创建schema,编辑dump或者如果你使用的是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(甚至使用管理工具以图形方式加载),唯一的警告是,您必须在加载具有相应源键的表之后加载具有外键的表。我没有循环依赖的情况,我想如果是这种情况,你可以暂时暂停键检查。

相关问题