python + sqlite3 - 无法使 blob 数据正常工作
python + sqlite3 - Can't get blob data to work
我知道这已被多次提及,但我似乎无法让它发挥作用。我正在编写一个 python 程序,它将接收一个 sqlite3 数据库转储文件,分析它并使用数据库迁移工具(称为 yoyo-migrations)重新创建它
我运行正在解决 sqlite3 中的 blob 数据问题以及如何正确格式化它。
这是我的程序执行的基本解释
- 读入转储文件,分成 CREATE 语句、INSERT 语句和其他语句
- 为 CREATEs 生成迁移文件
- 为每个 tables 插入生成一个迁移文件
- 运行 重建数据库的迁移(除了现在它是由迁移构建的)
基本上我得到了一个数据库,需要使用迁移来控制它。这只是第一步(使用迁移工具重建东西)
这里是 table blob table 的创建:
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);')
请注意,我只是将其写入文件,然后在最后 运行 迁移。接下来我需要正确的 "seed" 迁移来插入数据。这就是我 运行 遇到麻烦的地方!
# here is an example insert line from the dump
INSERT INTO blob_table VALUES(765,X'00063030F180800FE1C');
所以 X'' 的内容是 blob 数据,我需要编写一个 python 文件,将此数据插入回 table。我有大量数据,所以我使用了 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 东西起作用的提示!
buffer
class 能够处理二进制数据。但是,它会小心保存您提供给它的数据,并且 '00063030303031340494100'
不是二进制数据;它是一个包含数字零、零、零、六等的字符串。
要构建包含二进制数据的字符串,请使用 decode
:
import codecs
blob = buffer(codecs.decode(b'00063030303031340494100', 'hex_codec'))
我知道这已被多次提及,但我似乎无法让它发挥作用。我正在编写一个 python 程序,它将接收一个 sqlite3 数据库转储文件,分析它并使用数据库迁移工具(称为 yoyo-migrations)重新创建它
我运行正在解决 sqlite3 中的 blob 数据问题以及如何正确格式化它。
这是我的程序执行的基本解释 - 读入转储文件,分成 CREATE 语句、INSERT 语句和其他语句 - 为 CREATEs 生成迁移文件 - 为每个 tables 插入生成一个迁移文件 - 运行 重建数据库的迁移(除了现在它是由迁移构建的)
基本上我得到了一个数据库,需要使用迁移来控制它。这只是第一步(使用迁移工具重建东西)
这里是 table blob table 的创建:
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);')
请注意,我只是将其写入文件,然后在最后 运行 迁移。接下来我需要正确的 "seed" 迁移来插入数据。这就是我 运行 遇到麻烦的地方!
# here is an example insert line from the dump
INSERT INTO blob_table VALUES(765,X'00063030F180800FE1C');
所以 X'' 的内容是 blob 数据,我需要编写一个 python 文件,将此数据插入回 table。我有大量数据,所以我使用了 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 东西起作用的提示!
buffer
class 能够处理二进制数据。但是,它会小心保存您提供给它的数据,并且 '00063030303031340494100'
不是二进制数据;它是一个包含数字零、零、零、六等的字符串。
要构建包含二进制数据的字符串,请使用 decode
:
import codecs
blob = buffer(codecs.decode(b'00063030303031340494100', 'hex_codec'))