首页 > 解决方案 > SQLITE:Python 插入乱码而不是整数

问题描述

我似乎找不到以下问题的原因:

cur_out.execute("DROP TABLE IF EXISTS key2val");
cur_out.execute("DROP INDEX IF EXISTS key2val_value_index");
cur_out.execute("CREATE TABLE key2val(key INTEGER PRIMARY KEY, val INT)");
cur_out.executemany("INSERT INTO key2val VALUES(?,?)",((key,value[next(iter(dictionary[key]))],) for key in dictionary));
cur_out.execute("CREATE INDEX key2val_value_index on key2val(val)");
con_out.commit();

其中value是一个 numpy 整数数组,dictionary是一个 dict,指向每个键的一组非空整数。

>>> for tup in ((key,value[next(iter(dictionary[key]))],) for key in dictionary):
>>>     print(tup)
(615063, 10548)
(615980, 0)
(629315, 10627)
(631978, 0)
(642585, 0)
(643574, 0)
(667025, 0)
(152076, 5406)
(393084, 0)
...

然后在数据库中

sqlite> select distinct val from key2val limit 10;

返回一些无法在终端中正确显示或复制到 stackoverflow 中的奇怪符号或其组合。

标签: pythonsqlitecasting

解决方案


这不是胡言乱语,至少不是胡言乱语。问题是这value是一个 numpy 数组,因此它的元素不是 Python 整数而是 numpyint32int64取决于您的版本(32 位或 64 位)。

这不是sqlite3模块的已知类型,因此它只存储字节表示。例如,在我的带有 32 位 Python 的 little endian 系统上,它存储为 7 个b'\x07\x00\x00\x00'. 如果您显示这些值,这是明确repr的,但如果您只是打印它们,则很难猜测会发生什么。

怎么修:

恕我直言,最简单的方法是显式强制转换为 Python 整数类型:

cur_out.executemany("INSERT INTO key2val VALUES(?,?)",
                    ((key,int(value[next(iter(dictionary[key]))]),) for key in dictionary))

或者,您可以注册一个适配器:

def npint_adapt(x):
    return int(x)

sqlite3.register_adapter(np.int32, npint_adapt) # or use np.int64 here if using 64 bits...

然后直接插入np.int32(resp. np.int64)类型:

cur_out.executemany("INSERT INTO key2val VALUES(?,?)",
                    ((key,value[next(iter(dictionary[key]))],) for key in dictionary));

推荐阅读