MySQL cursors.execute() только с одним параметром: почему строка разделена на список?

#python #mysql #mysql-workbench

#python #mysql #python-2.7 #mysql-connector-python

Вопрос:

Статус-кво:

У меня есть рабочая база данных с таблицами, и я могу запрашивать, вставлять, обновлять и т.д. Также курсор подключен к нужной базе данных.

Таблица:

скриншот результата запроса

Проблема:

Когда дело доходит до запроса данных из таблицы, у меня возникают проблемы:

 query     = 'SELECT Last_Request_Time FROM Products WHERE idProduct = %s'
idProduct = '106'
cursor.execute(query, (idProduct))
  

Во время отладки я смотрю на функцию cursor.execute(): params = str: 106 будет передана в:

 stmt = operation % self._process_params(params)
  

где

 res = params
# pylint: disable=W0141
res = map(self._connection.converter.to_mysql, res)
  

вызывается с res = str: 106 . Я не уверен, что делает конвертер, но как результат res = list: ['1', '0', '6'] . И эти аргументы будут переданы функции execute, которая выдаст следующую ошибку:

 File "C:Python27libsite-packagesmysqlconnectorcursor.py", line 480, in execute
"Wrong number of arguments during string formatting")
mysql.connector.errors.ProgrammingError: Wrong number of arguments during string formatting
  

Плохое решение:

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

 query     = 'SELECT Last_Request_Time FROM Products WHERE idProduct = %s AND Edition != %s'
idProduct = '106'
cursor.execute(query, (idProduct, 'A'))
  

Ответ №1:

Проблема в том, что ('hello') это строка, а ('hello',) это кортеж. Вам нужно всегда передавать кортеж (или другую подобную коллекцию, например, список) в качестве значений для ваших заполнителей. Причина в том, что ваши заполнители являются позиционными в вашем запросе, поэтому аргументы также должны иметь некоторый порядок, а кортежи и списки — это два способа получить упорядоченный выбор объектов.

Поскольку он ожидает кортеж или другую коллекцию, 106 преобразуется в [1, 0, 6] . Если вы передадите (106,) , это будет интерпретировано правильно.

За кулисами происходит вот что:

 >>> for i in '106':
...     print(i)
...
1
0
6
>>> for i in ('106',):
...    print(i)
...
106
  

Итак, ваш «взлом» на самом деле правильное решение, вам просто не нужна дополнительная переменная:

 q = 'SELECT Last_Request_Time FROM Products WHERE idProduct = %s'
cursor.execute(q, (idProduct,))
  

Комментарии:

1. Это был быстрый ответ! Я попытался создать из этого список / кортеж, но не смог найти решение. Но это было довольно просто. Итак, когда дело доходит до python, нужно многому научиться.