数据查询
进行数据查询之前,需要先按照前文的方法获取一个数据库连接会话,在Web服务等需要并行数据库操作的情况下建议使用连接池进行操作。
Query
对象代表着一个查询,这是由Session的query()
方法创建的。query()
方法中可以列举要查询的类名称,或者类属性名称,例如session.query(User)
或者session.query(User.id)
。如果是采用经典式模型定义,则Query
对象是由模型的查询方法创建的。Query
对象返回的查询结果都是命名元组类型的,命名元组的键都是各个类中定义的字段。如果排列了多个查询内容,则会使用类名称或者属性名称。具体可参考以下示例:
for row in session.query(User, User.name).all():
print(row.User, row.name)
使用sqlalchemy.orm
模块中的aliased()
函数可以为查询目标定义别名,定义之后需要使用别名在查询中进行访问。
查询筛选
筛选条件是查询中的主要内容,也是最常用的内容。Query
对象使用filter()
方法来对查询目标进行过滤,filter()
方法接受一个布尔表达式。多个filter()
方法连续使用表示各个筛选条件之间以and
连接。此外还可以从sqlalchemy
模块中引入and_()
和or_()
方法来组装and
和or
条件。
大部分条件都定义在Column
对象上,常用的有:
query.filter(User.id == id)
,判断相等;query.filter(User.id != id)
,判断不相等;query.filter(User.name.like('%th%'))
,区分大小写的LIKE判断;query.filter(User.name.ilike('%th%'))
,不区分大小写的LIKE判断;query.filter(User.name.in_(['jack', 'kate']))
,是否在列表或者子查询中的判断;query.filter(~User.name.in_(['jack', 'kate']))
,是否不在列表或者子查询中的判断;query.filter(User.name.is_(None))
,判断是否为空;query.filter(User.name.isnot(None))
,判断是否为非空;query.filter(and_(User.name == 'a', User.age < 20))
,AND条件联合;query.filter(User.name == 'a', User.age < 20)
,AND条件联合;query.filter(User.name == 'a').filter(User.age < 20)
,AND条件联合;query.filter(or_(User.name == 'a', User.age < 20))
,OR条件联合。
还可以直接使用原生SQL文字来书写比较繁琐的查询条件,如果其中需要参数,可以使用params()
方法传递相应的参数进去。例如:
session.query(User).filter(text('age>:minage and age<:maxage')).params(minage=10, maxage=25).all()
获取查询内容
查询需要使用以下方法来获取查询的结果。
.all()
,获取全部结果,返回一个列表;.first()
,获取第一条数据,返回一个表示行的命名元组;.one()
,获取一条数据,如果结果不唯一或者无结果会报错;.one_or_none()
,获取一条数据,如果结果为空不会报错;.scalar()
,与.one()
类似,但返回第一列的内容;.count()
,返回结果集长度。
对于排序和分组,可以使用Query对象的.order_by()
和.group_by()
方法,使用方式很简单,只需要传入要操作的列即可。.order_by()
默认采用升序排列,如果需要降序,可以使用Column类中的.desc()
方法来声明,当然升序也可以使用.asc()
方法来显式声明。例如:query.order_by(User.age.desc())
。
关联查询
关联查询是数据库查询的一项重要内容。SQLAlchemy提供了多种方法来完成关联查询。
如果不打算使用显式的.join()
方法,可以直接将要关联查询的映射类都放在.query()
方法中。SQLAlchemy将返回条件合适的元组供使用。例如:
for u, r in session.query(User, Role).filter(User.id==Role.user_id).all();
print(u)
print(r)
如果使用.join()
方法,则会将被关联的子表结果放在定义的关联映射里。
for u in session.query(User).join(Role).all():
print(u)
.join()
方法还有若干使用方式,可以自动推断如何建立关联。
query.join(Role, User.id==Role.user_id)
,显式条件关联;query.join(User.roles)
,从左至右的关联定义;query.join(Role, User.roles)
,同上,显式指定关联目标;query.join('roles')
,同上,以字符串指定关联目标。