【问题标题】:Python MySQLdb/mysqlclient: bind a named set (or tuple or list) as parameterPython MySQLdb/mysqlclient:绑定命名集(或元组或列表)作为参数
【发布时间】: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() 的联接不感兴趣,尽管如果没有其他方法,我最终可能会走这条路。

我真正追求的是一个干净的习惯用法,它绑定命名的可迭代参数(如果有的话)。

【问题讨论】:

    标签: python mysql python-3.x mysql-python named-parameters


    【解决方案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 搞砸了,那么我建议以某种方式获取直接光标。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-16
        • 2012-10-01
        • 2021-04-17
        • 1970-01-01
        • 2011-10-17
        • 2014-11-20
        • 1970-01-01
        相关资源
        最近更新 更多