SQLAlchemy的in_方法查询包含None/NULL值的列表不生效如何解决?
原因说明
这是SQL标准的三值逻辑特性导致的,和SQLAlchemy本身的实现无关:
- 在SQL语法中,
NULL代表未知值,任何= NULL的比较操作返回的结果都是UNKNOWN,而非布尔值TRUE IN操作符本质是多个=条件的OR拼接,当你写multiplier IN (1,2,5,None),最终会被解析为:
最后一个条件永远返回multiplier = 1 OR multiplier = 2 OR multiplier =5 OR multiplier = NULLUNKNOWN,所以自然无法匹配到multiplier为NULL的行- 只有
IS NULL操作符能正确判断值是否为NULL,这也是你单独过滤NULL值时用== None能生效的原因:SQLAlchemy会自动把column == None转译为column IS NULL,但这个转译不会在IN语句的列表元素中生效。
解决方法
推荐通用的兼容所有SQL方言的实现方案:
- 先对传入的过滤值列表做拆分,分离普通值和NULL标记:
from sqlalchemy import or_ filter_list = [1,2,5, None] # 拆分普通值和None normal_values = [v for v in filter_list if v is not None] has_none = None in filter_list
- 拼接过滤条件,用
or_组合IN查询和NULL判断:
query = db.query(models.Data) conditions = [] if normal_values: conditions.append(models.Data.multiplier.in_(normal_values)) if has_none: conditions.append(models.Data.multiplier.is_(None)) # 组合条件后执行查询 result = query.filter(or_(*conditions)).all()
补充注意点:
- 推荐用
column.is_(None)替代column == None写法,更符合SQLAlchemy的规范,可读性更强 - 不要尝试把NULL放到IN列表里处理,该写法在所有标准SQL实现中都不会生效
内容的提问来源于stack exchange,提问作者Martin Fischer
相关产品推荐
相关产品推荐

