使用pymysql时IN子句占位符失效引发警告问题求助
解决PyMySQL中IN子句占位符的警告问题
这个坑我踩过好几次!你遇到的警告,根源是把多个ID拼成单个字符串传给%s占位符,PyMySQL会把它当作一个完整的字符串参数处理,最终生成的SQL会变成:
SELECT ... WHERE n.note_on_thing_id IN ('1, 2, 3, 4')
这显然不符合IN子句的语法(它需要的是多个独立的数值,不是一个带逗号的字符串),所以会触发类型不匹配的警告,甚至可能查不出正确结果。
正确的解决方法
方法1:用列表传参+动态生成占位符
把ID存成列表(而不是字符串),然后根据列表长度生成对应数量的%s占位符:
# 用整数列表存储ID,不要拼成字符串 thing_ids = [1, 2, 3, 4] # 生成和ID数量一致的占位符,用逗号分隔 placeholders = ', '.join(['%s'] * len(thing_ids)) # 把占位符拼进SQL语句 sql = f"SELECT n.note_id, n.note_info, ... FROM note n, contact c WHERE n.note_created_by=c.contact_id AND n.note_on_thing_id IN ({placeholders})" # 直接把列表作为参数传入 list_notes = db_get_list(sql, thing_ids)
这样PyMySQL会自动把列表里的每个元素作为独立参数转义后拼入SQL,既安全(防SQL注入),又完全符合语法要求。
方法2:如果ID是字符串格式,先转成列表
如果你的thing_ids已经是逗号分隔的字符串(比如从前端接收的参数),先把它转成整数列表再用上面的方法:
thing_ids_str = "1, 2, 3, 4" # 分割字符串并转成整数,注意处理空格 thing_ids = [int(id.strip()) for id in thing_ids_str.split(',')] # 后续步骤和方法1一致 placeholders = ', '.join(['%s'] * len(thing_ids)) sql = f"SELECT ... WHERE n.note_on_thing_id IN ({placeholders})" list_notes = db_get_list(sql, thing_ids)
重要提醒
- 绝对不要直接把字符串拼进SQL(比如
IN ({thing_ids_str})),这会引入SQL注入漏洞,非常危险! - 如果ID可能包含非数字内容,记得加异常处理,避免
int()转换报错。
内容的提问来源于stack exchange,提问作者andyd
相关产品推荐
相关产品推荐

