Написание простого запроса, получение unicodeEncodeError, python 2.7

Запрос:

query = "SELECT * from "+str(tablename)+" where user='"+str(user)+"' AND review_title='"+rt+"'"

Сообщение об ошибке:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 3: ordinal not in range(128)

Код:

rt = review_title.replace("'", "\\'")
rt = rt.replace('"', '\\"')
rt = unicode(rt).encode('utf-8')
query = "SELECT * from "+str(tablename)+" where user='"+str(user)+"' AND review_title='"+rt+"'"

В этом случае имя таблицы — 'ta_rest_review', user'KANNONEPL...', а rt'Excelente pero \"OJO a la CUENTA\"'.


person Lawrence DeSouza    schedule 26.10.2014    source источник
comment
У вас есть символ é где-то в ваших значениях, но в вашем образце ввода этот символ отсутствует.   -  person Martijn Pieters    schedule 26.10.2014
comment
При сообщении о проблеме с Python всегда включайте трассировку. Если это фактическое назначение query, то символ é с акцентом находится либо в значении user, либо в значении tablename.   -  person Martijn Pieters    schedule 26.10.2014
comment
В этом случае ваша проблема с UnicodeEncodeError вызвана вызовом str() для объекта unicode с символами за пределами допустимого диапазона ASCII, что является совершенно другой проблемой из сообщения вы прокомментировали ранее.   -  person Martijn Pieters    schedule 26.10.2014


Ответы (1)


Вы не должны не использовать форматирование строк для интерполяции данных. Вместо этого используйте параметры SQL!

Используйте соответствующий синтаксис параметра запроса для вашего драйвера базы данных, он будет использовать либо вопросительные знаки, либо %s заполнители:

cursor.execute(
    'SELECT * from {0} WHERE user=%s AND review_title=%s'.format(tablename),
    (user, rt)
)

Вам все равно придется интерполировать имя таблицы (убедитесь, абсолютно убедитесь, что это существующее имя таблицы, не принимайте пользовательский ввод, чтобы определить это!)

Затем драйвер базы данных может позаботиться о правильном экранировании значений user и rt, включая кодирование значений Unicode в кодировку, поддерживаемую базой данных.

Кроме того, вы избежите риска бреши в безопасности SQL-инъекций, если попытаетесь «избежать» входа в базу данных самостоятельно.

Посмотрите документацию по драйверу вашей базы данных; модуль должен иметь paramstyle переменную, которая определяет стиль заполнителя параметра поддерживает драйвер, а также объясните, поддерживаются ли несколько стилей.

person Martijn Pieters    schedule 26.10.2014
comment
Это сработало, спасибо за ваш ответ. Странно, что я не мог найти его здесь раньше. - person Lawrence DeSouza; 26.10.2014