Python3 x SQLite でリストをIN句に渡したい時

プログラム

例えばweb画面にチェックボックスを用意しておいて、python側でリストに格納した後にIN句に渡したいと。そんな時に。

結論


前提

内容には関係はないけど、念のため。

  • データベース:wnjpn.db
  • テーブル:word
  • 条件を絞りたいカラム:pos

“pos”カラムには、’n’、’v’、’a’、’r’ のどれかが格納されている。(どうでもいいけど、n=名詞、v=動詞、a=形容詞、r=副詞)

サンプルコード

どういう動きか

>>> list = ['n','v','a','r']
>>> query = 'SELECT * FROM word WHERE pos IN ({})'.format(', '.join(':{}'.format(i) for i in range(len(list))))
>>> query
'SELECT * FROM word WHERE pos IN (:0, :1, :2, :3)'

>>> params = ({str(i): part for i, part in enumerate(list)})
>>> params
{'0': 'n', '1': 'v', '2': 'a', '3': 'r'}

こんな感じでリストの要素数分、”:number”を埋め込んでqueryを作成。(query)

execute()で渡す引数のパラメータをタプルで作成。(params)

ちなみにこれでwordnetのDBでSELECTすると

>>> for row in cur.execute(query, params):
...     print(row)
... 
(155288, 'jpn', '頭金', None, 'n')
(155289, 'jpn', 'どうにかこうにか', None, 'r')
(155290, 'jpn', '大砲', None, 'n')
(155291, 'jpn', 'スチーム', None, 'n')
(155292, 'jpn', '溢れでる', None, 'v')
(155293, 'jpn', 'マーティニ', None, 'n')
(155294, 'jpn', '検閲官', None, 'n')
(155295, 'jpn', 'シャイラー', None, 'n')
(155296, 'jpn', 'イベリア', None, 'n')
(155297, 'jpn', '吃逆', None, 'n')

こんな感じになる。と。

 

その他

「%」を使用してフォーマットするやり方もある。以下は %を使いつつ、”:XXX” の形式ではなくて “?” でqueryを作る。

>>> query = 'SELECT * FROM word WHERE pos IN (%s)' % ','.join('?'*len(list))
>>> query
'SELECT * FROM word WHERE pos IN (?,?,?,?)'

これだと、SQLインジェクション対策ができていないという話を聞いたのだけど、不明。

コメント