Я знаю, как сопоставить список со строкой:
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-инъекции.)
Ответы:
Используйте
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-инъекций.
Обратите внимание, что data (
list_of_ids
) передается непосредственно драйверу mysql в качестве параметра (не в тексте запроса), поэтому инъекции нет. Вы можете оставить любые символы в строке, не нужно удалять или заключать символы в кавычки.источник
?
не%s
так, что он будет работать, если вы измените первую строку наformat_strings = ','.join('?' * len(list_of_ids))
.% format_strings
часть изменяла другие%s
заполнители в вашем запросе, толькоIN (%s)
заполнитель - способ добиться этого - удвоить все%
символы, кроме того, который вы хотите заменить:query = ("select distinct cln from vcf_commits where branch like %%s and repository like %%s and filename in (%s) and author not like %%s" % format_strings,); cursor.execute(query, (branch, repository) + tuple(fname_list) + (invalid_author,))
Хотя этот вопрос довольно старый, подумал, что лучше оставить ответ на случай, если кто-то еще искал то, что я хотел
Принятый ответ становится беспорядочным, когда у нас много параметров или если мы хотим использовать именованные параметры
После некоторых испытаний
ids = [5, 3, ...] # list of ids cursor.execute(''' SELECT ... WHERE id IN %(ids)s AND created_at > %(start_dt)s ''', { 'ids': tuple(ids), 'start_dt': '2019-10-31 00:00:00' })
Испытано с
python2.7
,pymysql==0.7.11
источник
Если вы используете
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
ссылка: https://stackoverflow.com/a/23891759/2803344 https://docs.djangoproject.com/en/2.1/topics/db/sql/#passing-parameters-into-raw
источник
Хотя это довольно старый вопрос. Делюсь своим решением, если оно кому-то поможет.
list_to_check = ['A', 'B'] cursor.execute("DELETE FROM foo.bar WHERE baz IN ({})".format(str(list_to_check)[1:-1])
Протестировано с
Python=3.6
источник
list_to_check
не экранировано с помощью SQL. Вот почему передача значений в качестве параметровexecute
более уместна. Используйте это решение очень осторожно (то есть входные идентификаторы не принимаются как параметры извне вашего приложения), так как кто-то может использовать это для атаки на вашу систему и доступа к вашей базе данных.Еще одно простое решение, использующее понимание списка:
# creating a new list of strings and convert to tuple sql_list = tuple([ key.encode("UTF-8") for key in list_of_ids ]) # replace "{}" with "('id1','id2',...'idlast')" cursor.execute("DELETE FROM foo.bar WHERE baz IN {}".format(sql_list))
источник
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)
источник
Очень просто: используйте приведенную ниже схему.
rules_id = ["9", "10"]
sql1 = "ВЫБРАТЬ * FROM_rules_staff посещаемости, ГДЕ id в (" + "," .join (map (str, rules_id)) + ")"
"," .join (карта (str, rules_id))
источник
rules_id
содержит"); DROP TABLES Bobby --
?