SQLAlchemy 1.3子查询filter条件被渲染为WHERE false问题
问题根因
子查询生成WHERE false恒假条件的核心原因是过滤条件编写错误:在SQLAlchemy表达式中错误使用了Python原生is关键字做布尔值判断。
SQLAlchemy的列对象仅重写了==、!=等比较运算符用于生成SQL语法树,而Python的is是判断两个对象内存地址是否一致的原生语法,不会触发SQLAlchemy的表达式重载逻辑。
代码中写的Article.is_activated is True会在Python运行时直接计算为布尔值False:Article.is_activated是SQLAlchemy的Column类实例,和Python内置的True单例内存地址完全不同,该表达式的返回值恒为False。SQLAlchemy接收到filter中传入的字面量False后,就会直接生成WHERE false的恒假条件,原本预期的字段过滤规则也不会被编译到SQL中。
修复方案
将过滤条件中的is True替换为SQLAlchemy支持的比较写法即可,可选两种写法:
- 用
==和布尔值做比较 - 直接引用布尔字段本身(SQLAlchemy会自动识别为真值判断)
修复后的核心代码如下:
from sqlalchemy import and_ subquery = ( session.query( Article.id, SubscriberArticle.subscriber_id, SubscriberArticle.data, SubscriberArticle.is_activated, ) .join(SubscriberArticle) .filter(and_( SubscriberArticle.subscriber_id == 1234, # 修复点:替换is为==,也可直接写Article.is_activated Article.is_activated == True )) .subquery() ) query = ( session.query( Article.id, Article.name, subquery.c.subscriber_id, subquery.c.data, subquery.c.is_activated, ) .join(subquery, subquery.c.id == Article.id) )
注意:编写SQLAlchemy过滤条件时,所有涉及列值的判断都不能直接使用Python原生
is/is not语法:这类判断是Python层面的即时运算,不会生成任何SQL表达式。除布尔值判断外,判断字段值为NULL时也不能写field is None,需要使用SQLAlchemy提供的专用方法field.is_(None)。
内容的提问来源于stack exchange,提问作者0x726974636879
相关产品推荐
相关产品推荐

