psycopg2 странное поведение

from django.db import connection

q = 'some value'

sql1 = 'SELECT * FROM table WHERE field LIKE %%%s%%' % q
sql2 = 'SELECT * FROM table WHERE field LIKE %%'+ q +'%%'

cursor = connection.cursor()
cursor.execute( sql1 ) #why exception: IndexError: tuple index out of range ?
cursor.execute( sql2 ) #works ok

3 ответа

Решение

Вы должны правильно указать свои аргументы SQL.

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

Правильный код:

q = "%"+q+"%"
cursor.execute( 'SELECT * FROM table WHERE field LIKE %s', (q,) )

Действительно правильный код:

q = "%"+q.replace("%","%%")+"%"
cursor.execute( 'SELECT * FROM table WHERE field LIKE %s', (q,) )

Предположим, что q = "a'bc". Сначала перепишите это как "% a'bc%". Затем используйте его в качестве обычного строкового аргумента. psycopg перепишет его как "%a\" bc% ", как и должно быть.

Если q может содержать "%", и вы хотите найти его, используйте второй.

Использование прямой манипуляции со строками почти наверняка приведет к неправильному SQL, который уязвим для атак SQL-инъекций ( см. Комментарий psycopg2 по этому вопросу).

Я думаю, что вы хотите сделать, это попытаться выполнить LIKE '%some value%' в django, верно?:

from django.db import connection
q = '%some value%'
cur = connection.cursor()
cur.execute("SELECT * FROM table WHERE field LIKE %(my_like)s", {'my_like': q})

Начиная с psycopg2 2.4.1, SQL, который выполняется на сервере:

SELECT * FROM table WHERE field LIKE '%some value%'

Вы должны правильно ЗАКАЗАТЬ вашу команду SQL:

sql1 = "SELECT * FROM table WHERE field LIKE '%%%s%%'" % q
sql2 = "SELECT * FROM table WHERE field LIKE '%"+ q +"%'"

И, цитируя правильно, я имею в виду использование одинарных кавычек с LIKE выражения.

Другие вопросы по тегам