2013-02-23 4 views
12

Я пытаюсь выполнить запрос в виде ..."SELECT ... WHERE ... IN" с неизвестным количеством параметров

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',)] 
>>> 

Это мой лучший вариант, или есть ли лучший способ обойти это?

+0

Возможный дубликат [SQLite: привязать список значений к «WHERE col IN (: PRM)»] (http://stackoverflow.com/questions/4788724/sqlite-bind-list-of-values-to-where -col-in-prm) – rsaxvc

ответ

6

Это ваш лучший вариант без использования дополнительных библиотек. У меня, конечно, advocated just that technique в прошлом, more than once на самом деле.

Вы также можете переключиться на использование SQLAlchemy, которая генерирует SQL для вас, но для этого вам необходимо подняться на свою кривую обучения и переписать большую часть вашего приложения.

+0

Справедливо, спасибо. Это было трудно найти, потому что важные термины - такие общие слова ... – glibdud

Смежные вопросы