5

在我的表模式中:

... disabled BOOLEAN, ...

连接数据库时:

db = sqlite3.connect(f, detect_types=sqlite3.PARSE_DECLTYPES)
sqlite3.register_converter("BOOLEAN", myfunc)

我像这样插入一条记录:

INSERT INTO mytable (disabled, ...) VALUES (:disabled, ...)

连同一个包含 disabled: False 的参数字典。

当我读回该记录时,会调用 myfunc 来转换 BOOLEAN 类型:

def myfunc(x):
    print x, type(x)

结果:(0, <type 'str'> 当我想要 False 时,它​​当然评估为 True)

我希望将布尔值存储为 1 字节整数,我只想在读取记录时将它们转换为 Python 布尔值(代码的其他部分需要布尔值而不是整数)。SQLite 是将它们存储为字符串,还是在调用 myfunc 之前将它们转换为字符串?为什么?

PS - 我尝试使用sqlite3.register_adapter(bool, int),但无济于事。

4

2 回答 2

21

您想对两个方向使用register_adapter和的组合:register_converter

sqlite3.register_adapter(bool, int)
sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))

SQLite 使用动态类型系统,但对于自定义类型,它无法确定0是字符串还是整数,因此您可以在此处返回字符串。

或者,使用:

sqlite3.register_converter("BOOLEAN", lambda v: v != '0')

当涉及到遗留数据时,这更加灵活和健壮,但也许您希望引发异常。

演示:

>>> import sqlite3
>>> db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
>>> sqlite3.register_adapter(bool, int)
>>> sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))
>>> db.execute('CREATE TABLE foo (bar BOOLEAN)')
<sqlite3.Cursor object at 0x10a17a340>
>>> db.execute('INSERT INTO foo VALUES (?)', (True,))
<sqlite3.Cursor object at 0x10a17a3b0>
>>> db.execute('INSERT INTO foo VALUES (?)', (False,))
<sqlite3.Cursor object at 0x10a17a340>
>>> for row in db.execute('SELECT * FROM foo'):
...     print row
... 
(True,)
(False,)
于 2013-06-05T10:01:28.320 回答
2

sqlite3没有boolean类型 - 只需将您的字段存储为integer

>>> import sqlite3
>>> db = sqlite3.connect(':memory:')
>>> db.execute('create table test (col1 integer)')
<sqlite3.Cursor object at 0x3737880>
>>> db.execute('insert into test values (?)', (1,))
<sqlite3.Cursor object at 0x3737960>
>>> print list(db.execute('select * from test'))
[(1,)]

自定义转换器类型采用存储列的字符串表示形式,然后您应该使用它从中创建新类型...

如果你做了类似的事情:

db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
def myfunc(col):
    val = int(col) == 1
    print val, type(val)
    return val

sqlite3.register_converter('boolean', myfunc)

db.execute('create table blah (something boolean)')
db.executemany('insert into blah values (?)', [(True,), (False,)])
list(db.execute('select * from blah'))

你会得到一个bool返回,这是我认为你想要的 - 但是,你需要确保处理异常,否则它们会被默默地压制......

于 2013-06-05T09:52:18.490 回答