sqlite3にはリスト型は存在しないため、例えばintegerのリストを格納したい場合はstr()して;(セミコロン)区切りの文字列にjoin()して格納、取り出すときはsplit()してint()するという操作が必要となる。
sqlite3モジュールにはこれらの操作を予め登録し必要に応じて自動で実行する仕組みが存在している。
これによりリスト要素の型が全て一致していることがわかっているのであれば、変換関数をregister_adapter()とregister_converter()を使って登録することでリストをシームレスに扱うことができる。
以下の例ではtesttableにIntListという型を定義してregister_adapter()とregister_converter()を使いpythonのデータ型との変換方法を登録している。
connectするときのdetect_types = sqlite3.PARSE_DECLTYPESは必須。
import sqlite3
CREATE_TABLE = u"""
create table if not exists testtable (
id integer primary key,
intlist IntList
);
"""
IntList = list
sqlite3.register_adapter(IntList, lambda l: ';'.join([str(i) for i in l]))
sqlite3.register_converter("IntList", lambda s: [int(i) for i in s.split(';')])
def main():
con = sqlite3.connect(":memory:", detect_types = sqlite3.PARSE_DECLTYPES)
con.row_factory = sqlite3.Row
con.execute(CREATE_TABLE)
insert_list = [1,2,3]
con.execute(u'insert into testtable values(?, ?)', (1, insert_list))
con.commit()
cur = con.cursor()
cur.execute(u'select * from testtable;')
assert insert_list == cur.fetchone()['intlist']
if __name__ == '__main__':
main()
register_adapter()とregister_converter()はユーザ定義の型でももちろん利用可能。
参考: http://docs.python.jp/2/library/sqlite3.html#id6