SQLAlchemy操作MSSQL原生SQL给WHERE IN传列表报错如何解决
问题根因
该报错由MSSQL的ODBC驱动特性导致:pyodbc不支持将元组/列表作为单个参数直接绑定,你之前看到的通用写法适配的是PostgreSQL、MySQL等支持数组参数的数据库驱动,无法直接在MSSQL环境生效。
适配MSSQL的解决方案
方案1:使用expanding参数(最推荐)
SQLAlchemy提供了expanding参数专门用于IN子句的列表参数绑定,会自动根据传入的列表长度生成对应数量的占位符,全程使用参数绑定避免注入风险,示例代码如下:
from sqlalchemy import text, bindparam id_list = [1, 2, 3] query = text("select * from table where col in :id").bindparams( bindparam("id", expanding=True) ) # 直接传列表即可,不需要转元组 conn.execute(query, {"id": id_list})
方案2:手动构造动态占位符
如果是较老版本的SQLAlchemy不支持expanding参数,可以手动生成和列表长度匹配的参数占位符,示例代码如下:
id_list = [1, 2, 3] # 生成独立参数名 param_keys = [f"id_{idx}" for idx in range(len(id_list))] # 拼接IN子句占位符 in_clause = ", ".join([f":{key}" for key in param_keys]) query = text(f"select * from table where col in ({in_clause})") # 构造参数字典 params = {param_keys[idx]: id_val for idx, id_val in enumerate(id_list)} conn.execute(query, params)
注意:不要直接把ID值拼接进SQL字符串,必须通过参数绑定传递,避免SQL注入风险
方案3:JSON解析适配长列表
如果IN子句的列表长度非常大(超过占位符数量限制),且使用的是SQL Server 2016及以上版本,可以通过JSON参数解析实现:
import json from sqlalchemy import text id_list = [1, 2, 3] query = text(""" select * from table where col in (select cast(value as int) from OPENJSON(:id_json)) """) # 将列表转成JSON字符串传入 conn.execute(query, {"id_json": json.dumps(id_list)})
内容的提问来源于stack exchange,提问作者jole5646
相关产品推荐
相关产品推荐

