Python supports chained comparisons:1 < 2 < 3
转换为(1 < 2) and (2 < 3)
。
我正在尝试使用SQLAlchemy进行SQL查询,如下所示:
results = session.query(Couple).filter(10 < Couple.NumOfResults < 20).all()
我得到的结果并不像预期的那样。我已经关闭了引擎的echo=True
关键字,实际上 - 生成的SQL查询只包含了两个比较中的一个。
我找不到任何明确说明这是禁止的文件。我假设如果Python支持这种类型的表达式,那么SQLAlchemy也应该支持它。
为什么这不起作用?我有一个可能的解决方案(在答案中分享),但很高兴听到其他意见。
答案 0 :(得分:3)
SQLAlchemy不支持Python的链式比较。以下是作者Michael Bayer的正式理由:
不幸的是,从python的角度来看,这可能是不可能的。 “x&lt; y&lt; z”的机制依赖于两个单独表达式的返回值。 SQLA表达式(如“column&lt; 5”)返回一个BinaryExpression对象,该对象的计算结果为True - 因此永远不会调用第二个表达式,我们永远不会有机会检测到表达式链。此外,需要检测表达式链并将其转换为BETWEEN,因为SQL不支持链式比较运算符。 不包括检测链 - > BETWEEN部分,为了使这项工作需要根据比较运算符的方向操纵BinaryExpression对象的
__nonzero__()
值,以便强制进行两次比较。向返回False的BinaryExpression添加基本__nonzero__()
说明当前代码库对它的容忍程度非常差,并且至少需要将几十种“如果x:”类型的检查转换为“如果x是无:“,但可能还有更难以解决的问题。对于外面的世界,它可能会造成严重破坏。 鉴于这里适当的SQL运算符是BETWEEN,可以从之间的运算符轻松访问,我不认为向后弯曲和令人困惑的人的价值是值得的所以这是一个“wontfix”。
详情请见: https://bitbucket.org/zzzeek/sqlalchemy/issues/1394/sql-expressions-dont-support-x-col-y
答案 1 :(得分:1)
原因是可能 Python实际上评估了这个表达式:
(10 < Couple.NumOfResults and Couple.NumOfResults < 20)
SQLAlchemy中不支持and
运算符(应该使用and_
代替)。因此,SQLAlchemy中不允许进行链式比较。
在原始示例中,应该编写此代码:
results = session.query(Couple).filter(and_(10 < Couple.NumOfResults,
Couple.NumOfResults < 20).all()