2016-03-21 2 views
1

У меня есть кортеж целого числа, я хочу запросить все строки со значением столбца, найденным в кортеже. Легко построить запрос, но я хочу, чтобы это было sql-инъекцией. Обычно я использую подготовленное заявление, но я не вижу, как справляться с обеими потребностями.MySQL и PYTHON. Как запросить WHERE 'column' IN tuple

Моей конструкция запроса выглядит следующим образом:

filterList = (1, 2, 4) #Taken as input. Should be integers 

sqlRequest = 'SELECT * FROM table' 
    if filterList != None and len(filterList) > 0: 
     sqlRequest += ' WHERE column IN (' 
     addComa = False 
     for filter in filterList: 
      if addComa: 
       sqlRequest += ',' 
      else: 
       addComa = True 
      sqlRequest += '%s'%(int(filter)) #casted to int to avoid SQL injection. Still not as good as I would like 
     sqlRequest += ')' 

    #At this point sqlRequest == 'SELECT * FROM table WHERE column IN (1,2,4)' 
    sqlResult = cursor.execute(sqlRequest) 

Я хотел бы иметь запрос больше как:

sqlRequest = 'SELECT * FROM table WHERE column IN (%s, %s, %s)' 

и выполнить его с подготовленным заявлением:

sqlResult = cursor.execute(sqlRequest, filterList[0], filterList[1], filterList[2]) 

Но filterList как переменная длина. Есть ли способ сделать что-то вроде?

sqlResult = cursor.execute(sqlRequest, filterList) #where filterList is the whole tuple 
+0

Точно так же, как с другими базами данных, см [Использование WHERE \ _ \ _ \ _ В \ _ \ _ \ _ оператор] (https://stackoverflow.com/q/14245396) и [Database API : Как это работает с несколькими, где условие в Python] (https://stackoverflow.com/q/19043987). –

+0

Извините, это не значит, что вы предлагаете редактировать, просто переустановите его на исправление размножения заполнителя. –

+0

Нет проблем. Я должен был сделать как минимум 6 изменений (включая некоторые бесполезные) для редактирования. –

ответ

2

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

statement = "SELECT * FROM table WHERE column IN ({0})".format(
    ', '.join(['%s'] * len(filterList))) 
cursor.execute(statement, filterList) 

Вы все еще можете проверить, что filterList не пусто, и опустить предложение WHERE вообще в этом случае:

statement = "SELECT * FROM table" 
if filterList: 
    statement += " WHERE column IN ({0})".format(
     ', '.join(['%s'] * len(filterList))) 
cursor.execute(statement, filterList) 
-1

вы сможете вставить его как полную строку в предложение mysql in.

inList = "','".join(str(i) for i in filterList) 
inList = r"'%s'" % inList 
sqlRequest = 'SELECT * FROM table WHERE column IN (%s)' 
sqlResult = cursor.execute(sqlRequest, inList) 
+0

Нет, потому что этот * SQL цитирует * строку, разделенную запятой. Если 'filterList' является' ['foo', 'bar', 'baz'] ', теперь вы ограничиваете свои строки теми, где' column' равно одной строке со значением '' foo, bar, baz''. –

+0

Мой плохой, я отредактировал его, чтобы он работал, сделав его необработанной строкой. –

+0

Нет, вы неправильно поняли, что делает сырая строка. И это * адаптер базы данных * использует «% s» placeholder для цитирования строкового значения в 'inList', чтобы предотвратить атаки SQL-инъекций (и в качестве возможности улучшения производительности, когда план запросов sqlRequest можно кэшировать независимо от значения параметров). Теперь я замечаю вторую ошибку, второй аргумент 'execute()' должен быть последовательностью; вы передали строку, поэтому * каждый отдельный символ * теперь является значением параметра. –