【问题标题】:Passing SQL Variable Using IN Expression in Python SQL Query在 Python SQL 查询中使用 IN 表达式传递 SQL 变量
【发布时间】:2020-04-11 09:41:34
【问题描述】:

在 Python 中传递 SQL 查询的最佳做法是使用 (?) 占位符。我遇到了一个问题,我的 SQL 查询有一个 IN 表达式,并且无法确定如何将变量参数传递给占位符。 编辑:这与其他答案不同(如 cmets 中指出的那样),其他答案不包括拆包。我的工作代码是:

cursor = conn.cursor()
query = "Select touchtonekey, COUNT(touchtonekey) as touchedthismanytimes from vw_callhandlertraffic\
            where callhandlername = ? and createddatetime between ?\
            and ? and touchtonekey IN ('1','2') Group By touchtonekey Order by touchtonekey"

data = cursor.execute(query,'My CallHandler','2019-10-09 13:00:00',
                      '2019-12-09 13:59:59')

但是当我尝试使用此代码删除 IN 参数时:

query = "Select touchtonekey, COUNT(touchtonekey) as touchedthismanytimes from vw_callhandlertraffic\
            where callhandlername = ? and createddatetime between ?\
            and ? and touchtonekey IN ? Group By touchtonekey Order by touchtonekey"

data = cursor.execute(query,'My CallHandler','2019-10-09 13:00:00',
                      '2019-12-09 13:59:59', "('1','2')")

我明白了:

Right hand side of IN expression must be a COLLECTION type.

如果我从括号中删除引号,我会得到:

Invalid application buffer type. (-11116) (SQLBindParameter)

【问题讨论】:

  • 这能回答你的问题吗? python list in sql query as parameter
  • 具体来说,this 回答,您需要在其中创建占位符。请注意,某些 SQL 方言对 IN 子句中可以包含的参数数量有限制
  • 哎呀,this 答案,甚至。他们基本上说同样的话。但实际上,他们缺少拆包

标签: python sql parameter-passing


【解决方案1】:

几乎python list in sql query as parameter 的骗子,但缺少一些东西:

  1. 您还有其他参数,而不仅仅是您的 IN 子句,因此您需要进行一些解包
  2. 关于某些 SQL 方言(例如 SQLite)对number of parameters you can pass 有限制的说明。

更正的代码:

cursor = conn.cursor()

membership_data = [1, 2] 
placeholders = ', '.join(['?' for item in membership_data])

query = """
        SELECT touchtonekey, COUNT(touchtonekey) AS touchedthismanytimes 
        FROM vw_callhandlertraffic
        WHERE callhandlername = ? AND createddatetime BETWEEN ? AND ? 
            AND touchtonekey IN ({}) 
        GROUP BY touchtonekey 
        ORDER BY touchtonekey
        """.format(placeholders) # Add the placeholders to your IN clause

data = cursor.execute(query,
                      ('My CallHandler',
                      '2019-10-09 13:00:00',
                      '2019-12-09 13:59:59',
                      *membership_data)) # Unpack the list

注意使用*the "splat"/"unpacking" operator 来为execute 制作一个扁平的参数元组

【讨论】:

  • 这是一个完美的解决方案。感谢@roganjosh 的帮助。
  • @RandyStegnerSr。如果您认为这已经回答了您的问题,请参阅What should I do when someone answers my question?(这也适用于您之前的问题)
  • 没有你@roganjosh 我该怎么办?感谢您帮助我解决的不仅仅是我遇到的问题!像您这样的用户让 Stack Overflow 如此出色。
【解决方案2】:

当我输入我的问题时,我想通了。由于我没有在 Stack Overflow 上看到答案(我可能只是找不到答案),我想我会发布这个问题然后回答它,以防它帮助其他人。关键是始终使用 = ?语法,然后在参数中包含 IN 关键字,如下所示:

cursor = conn.cursor()

    query = "Select touchtonekey, COUNT(touchtonekey) as 
             touchedthismanytimes from vw_callhandlertraffic\
             where callhandlername = ? and createddatetime between ?\
             and ? and touchtonekey = ? Group By touchtonekey Order by\ 
             touchtonekey"

    data = cursor.execute(query,'My CallHandler','2019-10-09 13:00:00',
                                 '2019-12-09 13:59:59',"IN ('1','2')")

【讨论】:

  • 不,这还没弄清楚。这是硬编码的。你最初的想法是正确的,只是你没有完全正确地执行它。
  • @roganjosh 同意,您永远不必在参数替换中包含关键字 IN
  • @roganjosh,那么正确的执行方式是什么?我不是开发人员,我只是为一些电信报告创建了一些脚本。任何帮助表示赞赏。
  • 我在你的问题下链接到它,两次
  • 我很抱歉,因为我完全错过了它。我未能刷新页面。不过,适当地注意到了未来。感谢您帮助一个菜鸟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多