我知道如何将列表映射到字符串:
foostring =",".join( map(str, list_of_ids) )
而且我知道我可以使用以下命令将该字符串放入IN子句中:
cursor.execute("DELETE FROM foo.bar WHERE baz IN ('%s')" % (foostring))
我需要使用MySQLDB安全地完成同一件事(避免SQL注入)。 在上面的示例中,由于foostring没有作为执行参数传递,因此它很容易受到攻击。 我还必须在mysql库之外引用和转义。
(有一个相关的SO问题,但是那里列出的答案对于MySQLDB无效或容易受到SQL注入的影响。)
您可能可以从php stackoverflow.com/questions/327274/中完成的类似问题中获得一些启发
SQL查询中python列表的可能重复项作为参数
@mluebke关于在查询中传递多个列表的任何想法吗?
直接使用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的驱动程序,因此没有注入。您可以在字符串中保留所需的任何字符,而无需删除或引用字符。
为什么在format_strings中引用%s?也可以通过.execute()方法来处理吗?
@heikogerlach:我没有引用%s ...第一行创建了一个字符串"%s,%s,%s" ...的长度与list_of_ids长度相同。
啊,你说的对。需要更加努力。我莫名其妙地把它混合了。不错的解决方案。
在sqlite中也可以使用吗?因为我刚尝试过,它似乎指出了语法错误。
在sqlite中,@ Sohaib的替换字符是?而不是%s,因此如果将第一行更改为format_strings = ,.join(? * len(list_of_ids)),它将起作用。
是的,我做了一点研究就知道了。虽然感谢您的帮助:)
根据这样的语句与不同数量的参数一起使用的频率,我希望对参数编号进行分组并执行多个以确保数据库仅看到有限数量的变体(对于sql缓存)。这也有助于避免过多的参数。
您能否为Python3中的相同解决方案提供示例语法?
@nosklo如果使用的查询对象具有例如fname_list = [item1, item2] 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 = churn_db_connection.get_connection_cursor() cursor.execute(query, (branch, repository, tuple(fname_list), invalid_author,))的参数,如何执行相同操作,则会引发错误
@kdas在您的情况下,您不希望% 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,))
啊,这真是棒极了@nosklo。 format_strings之后的逗号(,)引起错误,但删除后,它可以正常工作。天才。掌声。 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);
尽管这个问题已经很老了,但最好还是留下一个答案,以防其他人在寻找我想要的东西
当我们有很多参数或想要使用命名参数时,可接受的答案会变得混乱
经过一番试验
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'] #
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]}`;'
) #
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/zh-CN/2.1/topics/db/sql/#passing-parameters-into-raw
无痛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)
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 =" SELECT * FROM Attenance_rules_staff WHERE id in(" +"," .join(map(str,rules_id))+")"
","。join(map(str,rules_id))
它在哪里进行sql引用,这不是使用文字而不是绑定变量吗?
不需要,它只是工作正常。您可以测试因为元组结构直接用第一个大括号(" 9"," 10")转换为字符串。哪个调整sql格式。因此,您不需要其他格式即可使sql可调整
并且rules_id是否包含"); DROP TABLES Bobby --?
已经告诉"内嵌列表"而不是")" ...因此在查询之前,您需要验证
或使用:sql1 =" SELECT * FROM Attenance_rules_staff WHERE id in(" +"," .join(map(str,rules_id))+")"
如果您坚持使用数字,我猜它很好,但是仍然会产生带有文字的SQL,糟糕的SQL解析器...