具有未知数量参数的“SELECT ... WHERE ... IN”

时间:2013-02-23 14:23:37

标签: python sqlite

我正在尝试以......的形式执行查询。

SELECT col2 FROM tab WHERE col1 IN (val1, val2, val3...)

...其中值存储在任意长度的Python列表/元组中。我似乎无法找到一种“干净”的方式去做。

>>> db = connect(":memory:")
>>> db.execute("CREATE TABLE tab (col1 INTEGER, col2 TEXT)")
>>> db.execute("INSERT INTO tab VALUES(1,'one')")
>>> db.execute("INSERT INTO tab VALUES(2,'two')")
>>> db.execute("INSERT INTO tab VALUES(3,'three')")
>>> db.execute("INSERT INTO tab VALUES(4,'four')")
>>> db.execute("INSERT INTO tab VALUES(5,'five')")
>>> db.commit()

# Expected result
>>> db.execute("SELECT col2 FROM tab WHERE col1 IN (1,3,4)").fetchall()
[(u'one',), (u'three',), (u'four',)]

>>> vals = (1,3,4)

>>> db.execute("SELECT col2 FROM tab WHERE col1 IN (?)", vals).fetchall()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 3 supplied.

>>> db.execute("SELECT col2 FROM tab WHERE col1 IN (?)", (vals,)).fetchall()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.

>>> db.execute("SELECT col2 FROM tab WHERE col1 IN (?)", (','.join(str(val) for val in vals),)).fetchall()
[]

>>> 

现在我可以执行以下操作(我认为......如果我错了请纠正我)保留内置参数替换的安全性,但它仍然有点难看:

>>> db.execute("SELECT col2 FROM tab WHERE col1 IN (" + ",".join("?"*len(vals)) + ")", vals).fetchall()
[(u'one',), (u'three',), (u'four',)]
>>> 

这是我最好的选择,还是有更好的解决方法?

2 个答案:

答案 0 :(得分:7)

这是你最好的选择而不使用额外的库。我当然有advocated just that technique,事实上more than once

您也可以切换到使用SQLAlchemy,它为您生成SQL,但这需要您攀登其学习曲线并重写大部分应用程序。

答案 1 :(得分:0)

一个简单而干净的解决方案是:

vals = [1,3,4]
cursor.execute('SELECT col2 FROM tab WHERE col1 IN {}'.format(str(tuple(vals))