развертывание списка для использования в предложении Python MySQLDB IN - PullRequest
68 голосов
/ 26 февраля 2009

Я знаю, как отобразить список в строку:

foostring = ",".join( map(str, list_of_ids) )

И я знаю, что могу использовать следующую строку, чтобы вставить эту строку в предложение IN:

cursor.execute("DELETE FROM foo.bar WHERE baz IN ('%s')" % (foostring))

Мне нужно сделать то же самое БЕЗОПАСНО (избегая SQL-инъекций), используя MySQLDB. В приведенном выше примере, поскольку foostring не передается в качестве аргумента для выполнения, он уязвим. Я также должен процитировать и убежать за пределы библиотеки mysql.

(Существует связанный вопрос SO , но перечисленные там ответы либо не работают для MySQLDB, либо уязвимы для внедрения SQL.)

Ответы [ 5 ]

124 голосов
/ 26 февраля 2009

Используйте list_of_ids напрямую:

format_strings = ','.join(['%s'] * len(list_of_ids))
cursor.execute("DELETE FROM foo.bar WHERE baz IN (%s)" % format_strings,
                tuple(list_of_ids))

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

Обратите внимание, что данные (list_of_ids) направляются непосредственно в драйвер mysql в качестве параметра (не в тексте запроса), поэтому нет внедрения. Вы можете оставить любые символы в строке, нет необходимости удалять или заключать в кавычки символы.

0 голосов
/ 29 декабря 2018

Если вы используете Django 2.0 or 2.1 и Python 3.6, это правильный путь:

from django.db import connection
RESULT_COLS = ['col1', 'col2', 'col3']
RESULT_COLS_STR = ', '.join(['a.'+'`'+i+'`' for i in RESULT_COLS])
QUERY_INDEX = RESULT_COLS[0]

TABLE_NAME = 'test'
search_value = ['ab', 'cd', 'ef']  # <-- a list
query = (
    f'SELECT DISTINCT {RESULT_COLS_STR} FROM {TABLE_NAME} a '
    f'WHERE a.`{RESULT_COLS[0]}` IN %s '
    f'ORDER BY a.`{RESULT_COLS[0]}`;'
)  # <- 'SELECT DISTINCT a.`col1`, a.`col2`, a.`col3` FROM test a WHERE a.`col1` IN %s ORDER BY a.`col1`;'
with connection.cursor() as cursor:
    cursor.execute(query, params=[search_value])  # params is a list with a list as its element

ref: https://stackoverflow.com/a/23891759/2803344 https://docs.djangoproject.com/en/2.1/topics/db/sql/#passing-parameters-into-raw

0 голосов
/ 20 ноября 2017

Очень просто: просто используйте форму ниже

rules_id = ["9", "10"]

sql1 = "ВЫБРАТЬ * ОТ СЛУЖБЫ

"," .join (map (str, rules_id))

0 голосов
/ 05 сентября 2014
list_of_ids = [ 1, 2, 3]
query = "select * from table where x in %s" % str(tuple(list_of_ids))
print query

Это может работать в некоторых случаях, если вы не хотите интересоваться методом, в котором вам нужно передавать аргументы для завершения строки запроса, и вы хотите вызвать только cursror.execute(query).

Другой способ может быть:

"select * from table where x in (%s)" % ', '.join(str(id) for id in list_of_ids)
0 голосов
/ 24 ноября 2012

Безболезненный MySQLdb execute('...WHERE name1 = %s AND name2 IN (%s)', value1, values2)

def execute(sql, *values):

    assert sql.count('%s') == len(values), (sql, values)
    placeholders = []
    new_values = []
    for value in values:
        if isinstance(value, (list, tuple)):
            placeholders.append(', '.join(['%s'] * len(value)))
            new_values.extend(value)
        else:
            placeholders.append('%s')
            new_values.append(value)
    sql = sql % tuple(placeholders)
    values = tuple(new_values)

    # ... cursor.execute(sql, values)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...