前言
和Django一样,我们orm也要知道如何查询数据。
Query
Session
的query
函数会返回一个Query
对象。query
函数可以接受多种参数类型。可以是类,或者是类的instrumented descriptor。下面的这个例子取出了所有的User
记录。
|
|
Query
也接受ORM-instrumented descriptors作为参数。当多个参数传入时,返回结果为以同样顺序排列的tuples
|
|
Query
返回的tuples由KeyedTuple
这个类提供,其成员除了用下标访问意外,还可以视为实例变量来获取。对应的变量的名称与被查询的类变量名称一样,如下例:
|
|
你可以通过label()
来制定descriptor对应实例变量的名称
|
|
而对于类参数而言,要实现同样的定制需要使用aliased
|
|
基本的查询操作除了上面这些之外,还包括OFFSET和LIMIT,这个可以通过Python的array slice来完成。
|
|
上述过程实际上只涉及了整体取出的操作,而没有进行筛选,筛选常用的函数是filter_by
和filter
。其中后者比起前者要更灵活一些,你可以在后者的参数中使用python的运算符。
|
|
注意Query
对象是generative的,这意味你可以把他们串接起来调用,如下:
|
|
串接的filter
之间是与的关系。
常用的filter操作符
下面的这些操作符可以应用在filter
函数中
equals
:query.filter(User.name == ‘ed’)`
12* `not equals`:
query.filter(User.name != 'ed')
query.filter(User.name.like('%ed%'))
`query.filter(User.name.in_([‘ed’, ‘wendy’, ‘jack’]))
# works with query objects too:
query.filter(User.name.in_(
session.query(User.name).filter(User.name.like('%ed%'))
))`
|
|
query.filter(~User.name.in_(['ed', 'wendy', 'jack']))
`query.filter(User.name == None)
# alternatively, if pep8/linters are a concern
query.filter(User.name.is_(None))`
|
|
`query.filter(User.name != None)
# alternatively, if pep8/linters are a concern
query.filter(User.name.isnot(None))`
|
|
`# use and()
from sqlalchemy import and
query.filter(and_(User.name == ‘ed’, User.fullname == ‘Ed Jones’))
# or send multiple expressions to .filter()
query.filter(User.name == 'ed', User.fullname == 'Ed Jones')
# or chain multiple filter()/filter_by() calls
query.filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')`
|
|
from sqlalchemy import or_
query.filter(or_(User.name == 'ed', User.name == 'wendy'))
query.filter(User.name.match('wendy'))
>>> query = session.query(User).filter(User.name.like('%ed')).order_by(User.id)
SQL>>> query.all()
[<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>,
<User(name='fred', fullname='Fred Flinstone', password='blah')>]
>>> query.first()
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
没有查找到结果时:
1234
99).one() user = query.filter(User.id == Traceback (most recent call last): ... NoResultFound: No row was found for one()
one_or_none()
:从名称可以看出,当结果数量为0时返回None
, 多于1个时报错scalar()
和one()
类似,但是返回单项而不是tuple嵌入使用SQL
你可以在
Query
中通过text()
使用SQL语句。例如:123456789from sqlalchemy import text>>> for user in session.query(User).\... filter(text("id<224")).\... order_by(text("id")).all():... print(user.name)edwendymaryfred除了上面这种直接将参数写进字符串的方式外,你还可以通过
params()
方法来传递参数123"id<:value and name=:name")).\session.query(User).filter(text(... params(value=224, name='fred').order_by(User.id).one()<User(name='fred', fullname='Fred Flinstone', password='blah')>并且,你可以直接使用完整的SQL语句,但是要注意将表名和列明写正确。
|
|
# 计数
`Query`定义了一个很方便的计数函数`count()`
|
|
注意上面我们同时列出了实际的SQL指令。在SQLAlchemy中,我们总是将被计数的查询打包成一个子查询,然后对这个子查询进行计数。即便是最简单的`SELECT count(*) FROM table`,也会如此处理。为了更精细的控制计数过程,我们可以采用`func.count()`这个函数。
|
|
为了实现最简单的`SELECT count(*) FROM table`,我们可以如下调用
|
|
如果我们对`User`的主键进行计数,那么`select_from`也可以省略。
``
>>> session.query(func.count(User.id)).scalar()
SELECT count(users.id) AS count_1
FROM users
()
4
在下一篇教程里面我们将会介绍SQLAlchemy对于『关系』的处理方式,以及针对关系的更加复杂的查询。