Python MySQLdb/mysqlclient:绑定命名集(或元组或列表)作为参数
Posted
技术标签:
【中文标题】Python MySQLdb/mysqlclient:绑定命名集(或元组或列表)作为参数【英文标题】:Python MySQLdb/mysqlclient: bind a named set (or tuple or list) as parameter 【发布时间】:2015-10-11 23:17:40 【问题描述】:背景:关于 MySQLdb 连接器的文档不多
也许我找错地方了,但是关于 Python 的 mysqldb
连接器系列的文档并不多。也许PEP249 是为了完成这项工作。 Oracle 的 MySQL/Python 连接器似乎有更好的docs,但目前我正在使用mysqlclient(MySQLdb 的 3.x 版本,它环绕 C 连接器)。
MySQLdb 中的命名参数:适用于单个值
经过大量搜索,我偶然发现了用于绑定命名参数的漂亮语法,只要它们是单个值。例如(为简化案例而编造的查询):
query = """
SELECT...
WHERE
name = %(name)s AND
gender = %(gender)s
"""
parameters = 'name': name, 'gender': gender
cursor.execute(query, parameters)
这正确地转义了参数。太棒了。
MySQLdb中的命名参数:如何使用iterables?
现在我想使用集合、列表或元组来构建带有IN
的查询。比如:
query = """
SELECT...
WHERE
gender = %(gender)s AND
name IN %(nameset)s
"""
我发现了一个类似的问题here,但该查询不使用命名参数(占位符已命名,但不是可迭代的)。
我错过了什么?有人知道实现这项工作的神奇语法吗?
我在 MySQLdb 代码中看到 paramstyle
设置为 format
而不是 pyformat
,但 pyformat
确实适用于单个值。
为了澄清,
我对只构建像('sophie', 'jane', 'chloe')
这样的字符串并将其连接到查询的答案不感兴趣。我需要绑定参数来保证正确的转义。
我也对连接使用db.escape_string()
的联接不感兴趣,尽管如果没有其他方法,我最终可能会走这条路。
我真正追求的是一个干净的习惯用法,它绑定命名的可迭代参数(如果有的话)。
【问题讨论】:
【参考方案1】:不喜欢回答我自己的问题,但已经过了一天......
查看了 MySQLdb 代码,看来我不会如愿以偿。引用函数总是会添加太多的一组引号。
这就是我结束的地方(我提到的后备选项):
idset = ('Chloe', 'Zoe', "Noe';drip dautobus")
quoted_ids = [mdb.escape_string(identifier).decode('utf-8') for identifier in idset]
sql_idset = "('" + "', '".join(quoted_ids) + "')"
query = """
SELECT ...
FROM ...
JOIN ...
WHERE
someid = %(someid)s AND
namae IN """ + sql_idset
parameters = 'someid': someid
cursor.execute(query, parameters)
只绑定了一个参数。 IN
子句中的集合是预先引用的。
这不是我最喜欢做的事情,但至少每个值都通过 MySQLdb 引用函数运行,以便引用任何可能有害的东西。
decode
存在是因为escape_string
准备了一个字节字符串,但使用绑定参数someid
构建的query
是一个字符串。也许有更简单的方法。如果你找到了,请告诉我。
【讨论】:
【参考方案2】:我不知道如何在 MySQLdb 中具体表达它,但它可以与this other answer 中建议的 MySQL 连接器库(版本:1.4.4,MySQL 5.7.x)一起开箱即用:
cursor.execute('SELECT * FROM test WHERE id in %(l)s', 'l': (1,2,3))
如果 MySQLdb 搞砸了,那么我建议以某种方式获取直接光标。
【讨论】:
以上是关于Python MySQLdb/mysqlclient:绑定命名集(或元组或列表)作为参数的主要内容,如果未能解决你的问题,请参考以下文章