sqlalchemy or_()里面使用and_()出现问题
from sqlalchemy import create_engine, Column, Integer, String, and_, or_
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///test.db')
Base = declarative_base(engine)
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
Base.metadata.create_all()
Session = sessionmaker(bind=engine)
session = Session()
query = session.query(User).filter(
or_(User.name == 'Alice', User.name == 'Bob'),
and_(User.age > 18)
)
result = query.all()
for user in result:
print(f'User ID: {user.id}, Name: {user.name}, Age: {user.age}')
然而,当我们运行上面的代码时会发现并没有得到我们预期的结果,而是出现了一些奇怪的结果。
问题分析
造成这个问题的原因是在or_()函数里使用and_()时,会出现语法错误。or_()函数在SQLAlchemy中接受可变数量的表达式作为参数,并将这些表达式使用逻辑或操作符连接起来,生成一个新的条件。然而,and_()函数却是将其参数使用逻辑与操作符连接起来。因此,当将and_()函数用于or_()时,会导致SQLAlchemy生成的SQL语句结构不正确,从而得到错误的查询结果。
解决方法
为了解决上述问题,我们需要将or_()和and_()正确地嵌套在一起。正确的做法是将多个条件直接放在or_()或and_()函数里,而不是使用and_()嵌套在or_()里。
修改后的代码如下所示:
query = session.query(User).filter(
or_(
and_(User.name == 'Alice', User.age > 18),
and_(User.name == 'Bob', User.age > 18)
)
)
通过将and_()和or_()正确地组织,我们可以构建出符合我们需求的查询条件,从而得到正确的查询结果。
示例代码运行结果
下面是修改后的示例代码的运行结果:
User ID: 1, Name: Alice, Age: 20
User ID: 2, Name: Bob, Age: 25
可以看到,我们成功地得到了符合条件的用户数据。
总结
在使用SQLAlchemy构建复杂的查询条件时,需要注意or_()和and_()的使用方法,避免将and_()嵌套在or_()里造成错误的查询结果。通过正确的组织条件表达式,我们可以方便地构建出符合我们需求的查询语句。
极客教程