SQLAlchemy中的链式比较

时间:2012-09-12 15:15:04

标签: python database orm sqlalchemy

Python supports chained comparisons1 < 2 < 3转换为(1 < 2) and (2 < 3)

我正在尝试使用SQLAlchemy进行SQL查询,如下所示:

results = session.query(Couple).filter(10 < Couple.NumOfResults < 20).all()

我得到的结果并不像预期的那样。我已经关闭了引擎的echo=True关键字,实际上 - 生成的SQL查询只包含了两个比较中的一个。

我找不到任何明确说明这是禁止的文件。我假设如果Python支持这种类型的表达式,那么SQLAlchemy也应该支持它。

为什么这不起作用?我有一个可能的解决方案(在答案中分享),但很高兴听到其他意见。

2 个答案:

答案 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()