sqlite3.OperationalError: near "?": синтаксическая ошибка в python - использование оператора IN - PullRequest
2 голосов
/ 16 сентября 2011

Код:

print 'SELECT %s FROM %s WHERE %s %s %s' % (q_select, q_table, q_where, q_where_operator, q_value)
rows = cursor.execute('SELECT %s FROM %s WHERE %s %s ?' % (q_select, q_table, q_where, q_where_operator), (q_value,)).fetchall()

Результат:

SELECT ticket FROM my_table WHERE issue_key IN ('APSEC-2261')
Traceback (most recent call last):
  ...
  File "code.py", line 1319, in validate
    to_validate = db_query(q_select = 'ticket', q_table = 'my_table', q_where = 'issue_key', q_where_operator = 'IN', q_value = incident_query_list)
  File "code.py", line 1834, in db_query
    rows = cursor.execute('SELECT %s FROM %s WHERE %s %s ?' % (q_select, q_table, q_where, q_where_operator), (q_value,)).fetchall()
sqlite3.OperationalError: near "?": syntax error

Когда я выполняю точный запрос непосредственно к файлу SQLite в диспетчере SQLite Firefox, я получаю правильный ответ без ошибки:

SELECT ticket FROM my_table WHERE issue_key IN ('APSEC-2261')
179908

Обновление:

Попытка без подстановок %s и получение той же ошибки.

>>> test = cursor.execute('SELECT ticket FROM my_table WHERE issue_key IN ?', ('APSEC-2261',)).fetchall()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: near "?": syntax error

Обновление 2:

Попытка без ? Подстановка параметров DB-API, все та же ошибка.

>>> t = ('APSEC-2261',)
>>> cursor.execute('SELECT ticket FROM my_table WHERE issue_key IN ?', t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: near "?": syntax error

Обновление 3:

Почему оператор IN упоминается как имя_таблицы?

>>> cursor.execute('SELECT ticket FROM my_table WHERE issue_key IN \'APSEC-2261\'') 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: no such table: APSEC-2261

Обновление 4:

Исправлена ​​странная проблема с именем таблицы.

>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (\'APSEC-2261\')')
<sqlite3.Cursor object at 0x1723570>
>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (\'APSEC-2261\')').fetchall()
[(u'179708',)]

Обновление 5:

Невозможно написать собственное решение из-за менее чем 100 репутации. Проблема в том, что при использовании оператора IN в скобках должен быть ?.

>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (?)', ('APSEC-2261',))
<sqlite3.Cursor object at 0x1723570>
>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (?)', ('APSEC-2261',)).fetchall()
[(u'179708',)]

Поэтому мой метод db_query должен быть изменен на следующий

rows = cursor.execute('SELECT %s FROM %s WHERE %s %s (?)' % (q_select, q_table, q_where, q_where_operator), (q_value,)).fetchall()

Ответы [ 2 ]

3 голосов
/ 17 сентября 2011

Итак, есть несколько вопросов. Прежде всего, как вы обнаружили, круглые скобки являются частью синтаксиса предложения IN. Вы должны включить их.

Во-вторых, ваша команда будет работать нормально, пока q_value содержит одно значение. Но IN () действительно для использования с несколькими значениями, разделенными запятыми (для простого случая вы могли бы также использовать = вместо IN ()). Если вы попытаетесь передать список значений через запятую в одном параметре q_value, он не будет работать. SQLite будет обрабатывать весь список через запятую как одно значение для сопоставления.

В этом случае вы должны составить список разделенных запятыми вопросительных знаков и вставить их в свой SQL с форматированием строки. Затем необходимо создать список значений Python и передать этот список, чтобы указать одно значение на знак вопроса.

3 голосов
/ 17 сентября 2011

Проблема в том, что когда используется оператор IN, они должны иметь ? в скобках, (?).

>>> t = ('APSEC-2261',)
>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (?)', t)
<sqlite3.Cursor object at 0x1723570>
>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (?)', t).fetchall()
[(u'179708',)]
>>> # Show off how to check IN against multiple values.
...
>>> t = ('APSEC-2261','APSEC-2262')
>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (%s)' % (('?, ' * len(t))[:-2]), t)
<sqlite3.Cursor object at 0x1723570>
>>> cursor.execute('SELECT remediation_ticket FROM remediation WHERE issue_key IN (%s)' % (('?, ' * len(t))[:-2]), t).fetchall()
[(u'179708',), (u'180208',), (u'180240',), (u'180245',), (u'180248',), (u'180334',), (u'180341',), (u'180365',), (u'180375',)]

Мой вызов db_query был изменен, чтобы учесть несколько ? с q_value:

q_value_tuple = ()
for i in incidents:
    q_value_tuple += (i,)
tickets = db_query(q_select = 'remediation_ticket', q_table = 'remediation', q_where = 'issue_key', q_where_operator = 'IN', q_value = q_value_tuple)

Кроме того, мой метод db_query должен быть изменен на следующее:

rows = cursor.execute('SELECT %s FROM %s WHERE %s %s (%s)' % (q_select, q_table, q_where, q_where_operator, ('?, ' * len(q_value))[:-2]), q_value).fetchall()
...