如何为python MySQL.connector的IN查询传递列表参数?
问题核心原因
- 原代码的两处核心问题直接导致执行报错:
- 混用了SQL参数传递的两种机制:既提前用Python字符串格式化拼接SQL模板,又给
cursor.execute传入两组独立参数,既容易触发SQL注入风险,也会出现占位符和参数数量不匹配的报错。 - MySQL.connector 本身不支持将Python列表对象直接传入单个
%s占位符来匹配IN ()查询,驱动无法把列表自动解析成SQL可识别的逗号分隔值序列。
- 混用了SQL参数传递的两种机制:既提前用Python字符串格式化拼接SQL模板,又给
最佳实现步骤
- 根据传入列表的长度,动态生成对应数量的、用逗号分隔的
%s占位符字符串,占位符的数量和列表元素数量完全保持一致。 - 把动态生成的占位符结构嵌入SQL模板的对应
IN子句位置,注意这一步只替换占位符的格式结构,绝不直接拼接列表里的实际查询值。 - 把所有需要传入的查询参数按SQL中占位符出现的顺序,整合成一个扁平的参数列表/元组,统一传给
cursor.execute的第二个参数,全程不要混用字符串格式化和驱动自带的参数传值逻辑。
修正后的可运行示例
# 原始传入的列表参数 mdr_ids = ["1234", "5678"] sabs = ["Source1", "Source2"] # 动态生成对应IN子句的占位符结构 mdr_placeholder_str = ",".join(["%s"] * len(mdr_ids)) sab_placeholder_str = ",".join(["%s"] * len(sabs)) # 构建最终SQL模板 sql = f""" SELECT x.Code as MatchCode, m.CUI, GROUP_CONCAT(m.CODE separator '|') Codes, GROUP_CONCAT(m.SAB separator '|') Sources FROM umls.MRCONSO m, (SELECT * FROM umls.MRCONSO WHERE code in ({mdr_placeholder_str})) x WHERE x.cui = m.cui and x.sab in ({sab_placeholder_str}) GROUP BY m.CUI; """ # 按占位符出现顺序整合所有参数 execute_params = mdr_ids + sabs cursor.execute(sql, execute_params)
关键避坑点
- 所有实际的查询值必须通过驱动的参数传值通道传递,不要直接把列表内的原始值拼到SQL字符串里,从根源上避免SQL注入风险。
- 动态生成占位符时,只生成标准化的
%s结构,不要手动处理列表值的转义、引号包裹逻辑,这部分工作完全交给MySQL.connector驱动完成即可。 - 绝对禁止在同一次execute调用里同时用字符串拼值+驱动传参的混合写法,这种写法几乎一定会触发参数不匹配、占位符解析错误的问题。
内容的提问来源于stack exchange,提问作者mzbaran
相关产品推荐
相关产品推荐

