组合sql查询中列表参数的正确格式

Posted

技术标签:

【中文标题】组合sql查询中列表参数的正确格式【英文标题】:Correct format of list parameters in composed sql query 【发布时间】:2019-08-30 13:10:42 【问题描述】:

我正在尝试使用连接列表作为参数执行 sql 查询。 我已经建立了一个数据库连接,我想要一个类似的查询:

SELECT * FROM MYDATABASE.MY_TABLE
WHERE ( name IN ('name1','name2') );

所以我想将列表作为参数传递,变量过滤器是存储了正确格式但未实际使用的变量。 应该这样做的代码是:

my_list = ['name1', 'name2']
filters = ",".join(("''".format(key) for key in my_list))

q = sql.SQL('''SELECT * FROM MYDATABASE.MY_TABLE WHERE ( name IN () );''')
       .format(sql.SQL(', ')
       .join(sql.Placeholder() * len(my_list)))

cur = self.con.cursor()

query = q.as_string(context=self.con)
cur.execute(q)
results = cur.fetchall()
cur.close()

字符串查询是:

'SELECT * FROM MYDATABASE.MY_TABLE WHERE (name IN (%s, %s));'

,这似乎是正确的。 但是转义字符有一个错误,我找不到解决方法。 最后,我必须使用占位符而不是简单的 ".... 其中名称 = ".format() 解决方案,主要是出于安全原因。 有什么帮助吗?

编辑: 我尝试了所有建议,它们都给了我语法错误:

'错误:在“,”处或附近出现语法错误 第 1 行: ....MY_TABLE WHERE (name IN (?,?)) ... ..................................................... .................... ^'

【问题讨论】:

imploding a list for use in a python mysqlDB IN clause的可能重复 【参考方案1】:

试试这个:

cursor.execute("SELECT * FROM MYDATABASE.MY_TABLE WHERE (name IN (?,?))",my_list[0], my_list[1])

【讨论】:

你可以在那里申请解包cursor.execute("SELECT * FROM MYDATABASE.MY_TABLE WHERE (name IN (?,?))", *my_list) 这是一个只有 2 个项目的列表的解决方案,但列表的长度可以并且每次调用都会有所不同。那么这将如何在每次通话中使用不同的长度?【参考方案2】:
placeholder = '?'
placeholders = ', '.join(placeholder for unused in mylist)
query = "SELECT * FROM MYDATABASE.MY_TABLE WHERE (name IN (%s))" % placeholders
list = ",".join(my_list)    
cursor.execute(query, list)

【讨论】:

我得到一个例外:字符串格式化期间并非所有参数都转换了 对不起,我又错过了一行,现在检查一下 这应该可以工作,我得到与开头相同的错误 :syntax error at syntax error at or near "," LINE 1: ...E.MY_TABLE name IN (?, ?)和 现在尝试最后一次更改【参考方案3】:

您可以简单地使用",".join(my_list),这会将您的表格与“', '”作为分隔符连接起来:

my_list = ['name1', 'name2', 'name3', 'name4']
joined_list = "', '".join(my_list)   # Returns: "name1,name2,name3"

formatted = f"SELECT * FROM MYDATABASE.MY_TABLE WHERE ( name IN ('joined_list') )"
print(formatted) # Result: "SELECT * FROM MYDATABASE.MY_TABLE WHERE ( name IN ('name1', 'name2', 'name3', 'name4') )"

编辑:这是避免 SQL 注入的更好解决方案

my_list = ['name1', 'name2', 'name3', 'name4']
place_holders = "?," * (len(my_list) -1) + "?"

formatted = f"SELECT * FROM MYDATABASE.MY_TABLE WHERE ( name IN (place_holders) )"
print(formatted) # Result: "SELECT * FROM MYDATABASE.MY_TABLE WHERE ( name IN (?,?,?,?) )"

【讨论】:

这给了我一个语法错误,因为要使查询成功,名称必须单引号为:'name1'。这只有在joined_list是:filters = ",".join(("''".format(key) for key in my_list)) 时才有效但是在这种情况下的问题是它是否可以安全地免受sql注入,等 不,这不安全。我在答案中添加了另一种方法来处理占位符,因此您可以解压缩列表以在执行时将其作为参数传递 所以,现在我得到一个 TypeError ,可能是因为做错了什么,“函数最多接受 2 个参数(3 个给定)”。我将列表解压缩为: cur.execute(q, *my_list) 哎呀,我错过了,当您执行查询时只需将一个元组传递给它,它会在执行过程中解包。在你的情况下应该像 cur.execute(q, tuple(my_list)) 我得到了与从一开始就得到的相同的 SyntaxError:在“,”或附近出现语法错误 LINE 1: ....MY_TABLE WHERE (name IN (?,?)) ... ^

以上是关于组合sql查询中列表参数的正确格式的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在Microsoft SQL Server上为SQL查询设置超时?

sql linqlambda 查询语句的区别

SQL - 组合多个类似查询

Access 中两个任务列表的 SQL 查询 - 如何获得正确的“分配给”?

组合查询时的 SQL-server 语法错误(传递查询)

标准 SQL 查询在 BigQuery 中返回正确结果,但在 Data Studio 中不返回