在python MySQLDB IN子句中使用列表

mlu*_*bke 75 python mysql

我知道如何将列表映射到字符串:

foostring = ",".join( map(str, list_of_ids) )
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用以下内容将该字符串转换为IN子句:

cursor.execute("DELETE FROM foo.bar WHERE baz IN ('%s')" % (foostring))
Run Code Online (Sandbox Code Playgroud)

我需要的是使用MySQLDB安全地完成同样的事情(避免SQL注入).在上面的示例中,因为foostring不作为参数传递来执行,所以它很容易受到攻击.我还必须在mysql库之外引用并转义.

(有一个相关的SO问题,但那里列出的答案要么对MySQLDB不起作用,要么易受SQL注入攻击.)

nos*_*klo 137

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))
Run Code Online (Sandbox Code Playgroud)

这样你就可以避免引用自己,并避免各种sql注入.

请注意,data(list_of_ids)直接作为参数(不在查询文本中)直接转到mysql的驱动程序,因此没有注入.你可以在字符串中留下你想要的任何字符,不需要删除或引用字符.

  • @heikogerlach:我没有引用 %s ... 第一行创建了一个字符串 "%s,%s,%s" ... 与 list_of_ids 长度相同。 (2认同)
  • @Sohaib 在 sqlite 中,替换字符是“?”而不是“%s”,因此如果将第一行更改为“format_strings = ','.join('?' * len(list_of_ids))”,它就会起作用。 (2认同)
  • @kdas 在您的情况下,您不希望 `% format_strings` 部分更改查询中的其他 `%s` 占位符,只更改 `IN (%s)` 占位符 - 实现这一点的方法是将所有 ` %` 字符除了要替换的字符:`query = ("从 vcf_commits 中选择不同的 cln,其中分支如 %%s 和存储库如 %%s 和文件名在 (%s) 和作者不如 %%s" % format_strings ,); cursor.execute(query, (branch, repository) + tuple(fname_list) + (invalid_author,))` (2认同)

mar*_*rkk 11

虽然这个问题已经很老了,但我认为最好留下回复以防其他人正在寻找我想要的东西

当我们有很多参数或者我们想使用命名参数时,接受的答案会变得混乱

经过一些试验

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'
})
Run Code Online (Sandbox Code Playgroud)

测试python2.7pymysql==0.7.11

  • 这不适用于 python 3 和 mysql-connector-python 8.0.21。返回错误“Python元组无法转换为MySQL类型”。 (10认同)