【问题标题】:Python - pass a list as params to SQL, plus more variablesPython - 将列表作为参数传递给 SQL,以及更多变量
【发布时间】:2017-02-21 18:25:51
【问题描述】:

我正在尝试在 python 3.6 中将未知数量的参数传递给 SQL Server。这是我使用 pypyodbc 的代码:

cursor = cnxn.cursor()
theargs= ['1033286869','1053474957','1063654630','1104116235','1104910306','JASON']

thesql = """SELECT * 
            FROM BI_DUPLICATES_STAGE_0 
            WHERE DUP_ID IN (?, ?, ?, ?, ?)
            AND FRST_NM = ?
         """
cursor.execute(thesql, theargs)
resultset = cursor.fetchall()

这行得通。但是,我永远不确定我将拥有多少个 DUP_ID。我见过一些使用列表的例子,但是如果我有另一个变量,例如这种情况,FRST_NM,那么我不能只使用列表。

因此,如果有人可以提供一个简单的示例,说明有一个列表(不同长度)和另一个变量以及如何让 SQL 运行,我将不胜感激!如果这是问题所在,我不一定要使用 pypyodbc,而且还有另一种方法可以做到这一点。

更新: 感谢您提供格式精美的答案。只是一个快速的后续问题。如果我必须产生类似的东西,我仍然有点不清楚如何格式化 2 个列表: SELECT * FROM BI_DUPLICATES_STAGE_0 WHERE DUP_ID IN (1033286869, 1053474957, 1063654630, 1104116235, 1104910306) AND MID_NM IN ('SMITH','JON') AND FRST_NM = 'JASON'

如果没有好的格式加入,我会遇到这样的混乱: SELECT * FROM BI_DUPLICATES_STAGE_0 WHERE DUP_ID IN (?,?,?,?,?) AND MID_NM IN (?,?) AND FRST_NM = ?

如何按照建议将列表格式化两次?请记住,我不知道每个列表(ID 和 MID_NM)的实际长度。

【问题讨论】:

  • 我遇到了一些这样的问题...为什么那个查询是一团糟?这是参数化查询的准备语句。

标签: python sql sql-server pypyodbc


【解决方案1】:

考虑格式化字符串以根据列表长度、theargsotherargs 动态构建 ? 占位符。请注意,姓氏应位于参数列表的末尾,以对应于最后一个 ? 占位符。完成构建准备好的语句后,将参数值传递给cursor.execute()

theargs= ['1033286869','1053474957','1063654630','1104116235','1104910306']
otherargs = ['SMITH','JON']
lastarg = ['JASON']
allargs = theargs + otherargs + lastarg

thesql = """SELECT * 
            FROM BI_DUPLICATES_STAGE_0 
            WHERE DUP_ID IN ({})
            AND MID_NM IN ({})
            AND FRST_NM = ?
         """.format(",".join(['?' for i in range(len(theargs))]),
                    ",".join(['?' for i in range(len(otherargs))]))    
print(thesql)

# SELECT * 
#             FROM BI_DUPLICATES_STAGE_0 
#             WHERE DUP_ID IN (?,?,?,?,?)
#             AND MID_NM IN (?,?)
#             AND FRST_NM = ?

cursor.execute(thesql, allargs)

【讨论】:

  • 有趣!如果我的 WHERE 子句类似于: WHERE id IN (1,2,3) AND othervalue IN ('a','b','c') AND name = 'Bob' 会有一个聪明的方法来处理多个列表我没有看到的未知长度?我只是很惊讶没有一种简单的 IN (@list) 类型的参数来传递东西:)
  • 您需要为两个列表格式化两次。 SQL 是声明性语言。因此,一旦声明了表、列、变量,甚至像 WHEREGROUP BYJOIN 这样的子句,它就是不可变的。因此,它不能根据条件动态变化。 Python 可以动态构建字符串,但一旦构建,SQL 就可以在一次调用中处理。
  • 非常感谢您的回答。我已经通过一个小的跟进更新了这个问题。我有点不清楚如何为两个列表设置两次格式:)
  • 查看更新。只需用另一个 .join 字符串扩展 str.format()。还要注意FRST_NM 参数应该如何放在最后。顺便说一句,希望您的列表不会扩展到数千个,因为各种数据库在 IN() 子句中具有值限制。考虑对如此大的列表使用临时表。
猜你喜欢
  • 2021-11-03
  • 2021-06-01
  • 2019-03-02
  • 1970-01-01
  • 2020-01-13
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
相关资源
最近更新 更多