数据查询
进行数据查询之前,需要先按照前文的方法获取一个数据库连接会话,在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'),同上,以字符串指定关联目标。