2016-08-18 5 views
0

Я имею в виду что-то вроде этого:передавая много аргументов в одном заполнителе Джанго курсора (placeholer в IN)

from django.db import connection 
cursor=connection.cursor() 
cursor.execute('SELECT * FROM mytable where id IN (%s)', [params]) 

Параметры не могут быть просто итерацию - это не работает. Не может быть также в формате CSV из-за исключения значения обработчиком db.

Как использовать заполнитель в пределах IN?


По CSV не так, я имею в виду, что для params=['1','2','3','4','5']

c.execute('select * from mytable where id in (%s)', [','.join(params)]) 

будет производить:

select * from mytable where id in ('1,2,3,4,5') 

но правильный SQL является:

select * from mytable where id in (1,2,3,4,5) 

и, кажется, с заполнители.

+1

Не уверен, что вы подразумеваете под «не может быть в формате CSV». IN ожидает список значений, которые обязательно должны быть разделены запятой. Если ваши 'params' являются списком, вы должны сделать что-то вроде' ', '. Join (params)'. Это преобразует список как '[1, 2, 3]' в строку типа '1,2,3'. –

+0

Будьте осторожны с использованием '% s' в качестве заполнителя в SQl, он может оставить вас уязвимым для SQL-инъекции https://xkcd.com/327/ –

+0

@Chris_Rands: это не про фикцию' '% s"% params'. –

ответ

0

Вы не можете использовать IN для этого, так как на самом деле, в рассчитывает последовательность целых чисел, но ORM переводит список до ARRAY, и если вы используете join, вы получите строку.

Решение должно использовать эквивалент ANY. Форматирование немного отличается, но это должно работать для вас:

c.execute('select * from mytable where id = ANY(%s)', [params]) 

Учитывая params = [1, 2, 3, 4, 5], полученный в результате SQL будет:

SELECT * FROM mytable where id = ANY(ARRAY[1, 2, 3, 4, 5]) 

Обратите внимание, что это требует список идентификаторов, которые будут сделаны из Интс , поэтому, если у вас есть список строк, обязательно сначала их конвертируйте.

1

Обновлено Ответ Извините, о более старшем ответе. Это должно работать так, как вы хотите, но не лучшим решением. Я попробовал это с обоими параметрами как список строк и список целых чисел.

from django.db import connection 

params = [1, 2, 3, '4', '5'] 
placeholders = ('%s,'*len(params)).rstrip(',') # Having a comma at the end will give a syntax error 

with connection.cursor() as cursor: 
    cursor.execute('SELECT * FROM mytable where id IN ({})'.format(placeholders), params) 
    # Use the cursor here 

End обновленный ответ


В SQL значение для IN должен быть разделенный запятыми список

SELECT column_name(s) 
FROM table_name 
WHERE column_name IN (value1,value2,...); 

Так, самый простой подход для вас, при условии, что params является итерабельным, будет

from django.db import connection 
with connection.cursor() as cursor: 
    cursor.execute('SELECT * FROM mytable where id IN (%s)', [', '.join(params)]) 

Объединение преобразует ваши итерационные параметры в строку, разделенную запятой, которая затем заменит% s.

Как правило, вы хотите, чтобы ваши параметры запроса были экранированы. Даже данные, которые вы храните, должны быть экранированы.

Редактировать: Также обратите внимание, что я переместил курсор в блок with. Вы всегда должны закрыть свои соединения. Read up more here.

+0

это неправильный ответ, даст неверный результат. –

-1

Решение довольно простое:

c.execute('select * from mytable where id in (%s)' % (','.join(params),))

Смотрите же тему: imploding a list for use in a python MySQLDB IN clause

+0

Да, это так, но выше не использовать курсор placeholder - это довольно обходное решение. Однако, возможно, с обработчиком mysql db, использующим именованные параметры в запросе форматирования, но недоступным для django db-обработчика. –

+0

Я действительно пробовал его в оболочке Django. –

+0

Помните, что это АКТИВНО ОПАСНО. Используя стандартное форматирование строк, вы вводите вектор атаки SQL Injection, особенно если параметры относятся к любой форме данных, оставшихся слева от пользователя. Ни в коем случае не используйте этот код. –