python - 如何通过 SQLAlchemy 在 python 中的 sqlite3 db 中部分覆盖 blob?
问题描述
我有一个包含二进制表示的 blob 列的数据库,如下所示
我感兴趣的值在标记中被编码为 little endian unsigned long long (8 字节) 值。像这样读取这个值可以正常工作
p = session.query(Properties).filter((Properties.object_id==1817012) & (Properties.name.like("%OwnerUniqueID"))).one()
id = unpack("<Q", p.value[-8:])[0]
上面例子中的 id 是 1657266。现在我想做的是相反的。我有行对象 p,我有一个十进制格式的数字(出于测试目的使用相同的 1657266),我想以小端格式将该数字写入相同的 8 个字节。我一直在尝试通过 SQL 语句这样做
UPDATE properties SET value = (SELECT substr(value, 1, length(value)-8) || x'b249190000000000' FROM properties WHERE object_id=1817012 AND name LIKE '%OwnerUniqueID%') WHERE object_id=1817012 AND name LIKE '%OwnerUniqueID%'
但是当我这样做时,我就无法再阅读它了。至少不使用 SQLAlchemy。当我尝试与上面相同的代码时,我收到错误消息Could not decode to UTF-8 column 'properties_value' with text '☻'
,因此看起来它是以不同的格式编写的。有趣的是,在 DB Browser 中使用普通的 select 语句仍然可以正常工作,并且 blob 仍然与上面的屏幕截图完全相同。现在理想情况下,我希望能够使用 SQLAlchemy ORM 仅写入这 8 个字节,但如果需要的话,我会满足于原始 SQL 语句。
解决方案
通过基本上扭转我过去阅读它的过程,我设法让它与 SQLAlchemy 一起工作。事后看来,使用 + 连接和 [:-8] 分割正确的部分似乎很明显。
p = session.query(Properties).filter((Properties.object_id==1817012) & (Properties.name.like("%OwnerUniqueID"))).one()
p.value = p.value[:-8] + pack("<Q", 1657266)
通过为 SQLAlchemy 打开 ECHO,我得到了以下原始 SQL 语句:
UPDATE properties SET value=? WHERE properties.object_id = ? AND properties.name = ?
(<memory at 0x000001B93A266A00>, 1817012, 'BP_ThrallComponent_C.OwnerUniqueID')
如果你想手动做同样的事情,这不是特别有用。
值得注意的是,我的问题中的原始 SQL 语句不仅适用于使用 DB 浏览器阅读它,而且适用于使用相关数据库的游戏客户端。只有 SQLAlchemy 似乎有问题,试图将其解码为 UTF-8。
推荐阅读
- laravel - 如何在多态模型中存储和更新一条用户记录
- openapi - 如何在 OpenAPI 中定义未包装的响应?
- regex - 提取没有连续空格的文本
- assembly - 处理器如何知道寄存器值的顺序?
- linux - awk/sed 如何将骆驼 url 路径更改为下划线路径?
- python - 我是 Jupyter 的新手,不知道我在做什么有什么问题
- python - AllenNLP 语义角色标签 - SRLBert 错误
- java - 在 Flink 中的 KeyedProcessFunction 上停用 onTimer
- ios - NSLocalizeddescription=取消 IOS MFP
- python - 返回 HTTP json 响应