我知道这已被多次触及,但我似乎无法让这个工作。我正在编写一个python程序,它将接收一个sqlite3数据库转储文件,分析它并使用数据库迁移工具(称为yoyo-migrations)重新创建它
我遇到了sqlite3中blob数据的问题以及如何正确格式化它。
这是我的程序执行的基本解释 - 读入转储文件,分为CREATE语句,INSERT语句等 - 为CREATE生成迁移文件 - 为每个表插入生成一个迁移文件 - 运行迁移以重建数据库(现在除了迁移之外)
基本上我获得了一个数据库,需要使用迁移来控制它。这只是第一步(使用迁移工具重建事物)
这是blob表的表创建:
CREATE TABLE blob_table(
blockid INTEGER PRIMARY KEY,
block blob
)
然后我创建了迁移文件:
#
# file: migrations/0001.create_table.py
# Migration to build tables (autogenerated by parse_dump.py)
#
from yoyo import step
step('CREATE TABLE blob_table( blockid INTEGER PRIMARY KEY, block blob);')
请注意,我只是将其写入文件,然后最后运行迁移。接下来我需要找一个种子"插入数据的迁移。这是我遇到麻烦的地方!
# here is an example insert line from the dump
INSERT INTO blob_table VALUES(765,X'00063030F180800FE1C');
所以X'' stuff是blob数据,我需要编写一个python文件,将这些数据插入表中。我有大量的数据,所以我使用execute many语法。以下是种子迁移文件的样子(示例):
#
# file: migrations/0011.seed_blob_table.py
# Insert seed data for blob table
#
from yoyo import step
import sqlite3
def do_step(conn):
rows = [
(765,sqlite3.Binary('00063030303031340494100')),
(766,sqlite3.Binary('00063030303331341FC5150')),
(767,sqlite3.Binary('00063030303838381FC0210'))
]
cursor = conn.cursor()
cursor.executemany('INSERT INTO blob_table VALUES (?,?)', rows)
# run the insert
step(do_step)
我尝试使用sqlite3.Binary()
,python内置buffer()
,两者的组合以及int('string', base=16)
,hex()
和其他许多组合。无论我做什么,它都不会与转储中的数据库匹配。我的意思是:
如果我并排打开新旧数据库并执行此查询:
# in the new database, it comes out as a string
SELECT * FROM blob_table WHERE blockid=765;
> 765|00063030303031340494100
# in the old database, it displays nothing
SELECT * FROM blob_table WHERE blockid=765;
> 765|
# if I do this in the old one, I get the x'' from the dump
SELECT blockid, quote(block) FROM blob_table WHERE blockid=765;
765|X'00063030303031340494100'
# if I use the quote() in the new database i get something different
SELECT blockid, quote(block) FROM blob_table WHERE blockid=765;
765|X'303030363330333033303330... (truncated, this is longer than the original and only has digits 0-9
我的最终目标是重建数据库并使其与起始数据库(从中进行转储)相同。有关获取blob内容的任何提示都非常感谢!