sqlalchemy系列教程二-query对象

1,047 阅读2分钟

一 、关于Query的应用

Session的query函数会返回一个Query对象。query函数可以接受多重参数类型。可以是类,或者是类的instrumented descriptor(描述符)。
# 取出 User的所有记录
for instance in session.query(User).order_by(User.id):
	print (instance.name, instance.fullname)
    
Query也接受ORM-instrumented descriptors 作为参赛,当多个参数传入时,返回结果为以同样顺序排列的tuples
for name, fullname in session.query(User.name, User.fullname):
	print(name, fullname)
Query 返回的tuples由KeyedTuple这个类提供,其成员除了用下标访问以外,还可以视为实例变量来获取。对应的变量名称与被查询的类变量名称一样
for row in session.query(User, User.name).all():
...    print(row.User, row.name)
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')> ed
<User(name='wendy', fullname='Wendy Williams', password='foobar')> wendy
<User(name='mary', fullname='Mary Contrary', password='xxg527')> mary
<User(name='fred', fullname='Fred Flinstone', password='blah')> fred

你可以通过 label()来定制descriptor对应实例变量的名称

for row in session.query(User.name.label('name_label')).all():
...    print(row.name_label)
ed
wendy
mary
fred

而对于类参数而言,要实现同样的定制需要使用aliased

>>> from sqlalchemy.orm import aliased
>>> user_alias = aliased(User, name='user_alias')

SQL>>> for row in session.query(user_alias, user_alias.name).all():
...    print(row.user_alias)
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
<User(name='wendy', fullname='Wendy Williams', password='foobar')>
<User(name='mary', fullname='Mary Contrary', password='xxg527')>
<User(name='fred', fullname='Fred Flinstone', password='blah')>
OFFSET和LIMIT,这个可以通过Python的array slice来完成。
for u in session.query(User).order_by(User.id)[1:3]
	print(u)
<User(name='wendy', fullname='Wendy Williams', password='foobar')>
<User(name='mary', fullname='Mary Contrary', password='xxg527')>

上述过程只涉及了整体取出,没有进行筛选,筛选常用的函数时filter_by和filter。其中后者比起前者要更灵活一些,你可以在后者的参数中使用python的运算符。

for name in session.query(User.name).filter_by(fullname='shawna'):
	print name
    
for name in sesssion.query(User.name).filter(User.fullname=='shawna'):
	print name

Query对象是generative的,这意味着你可以把它们串联起来调用

串接的filter之间是与的关系。

for user in session.query(User).filter
(User.name=='shawna'
').filter(User.fullname=='Jones'):
	print user

<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>

常用的filter操作符

filter_by 通用吗?????

  • equals
query.filter(User.name == 'ed')
  • not equals
query.filter(User.name != 'ed')
  • LIKE
query.filter(User.name.like(%sha%))
  • IN
query.filter(User.name.in_(['as','ed', 'jack']))

query.filter(User.name.in_(session.query(User.name).filter(User.name.like('%jack%'))))
  • NOT IN
query.filter(~User.name.in_(['ed']))
  • IS NULL
query.filter(User.name.is_(None))
query.filter(User.name == None)
  • IS NOT NULL
query.filter(User.name != None)
query.filter(User.name.isnot(None))
  • AND
query.filter(User.name == 'shawna', User.fullname == 'Ed')

query.filter(and_(User.name == 'ed', User.fulllname == 'jack'))

query.filter(User.name == 'ed').filter(User.fullname == 'jack')
  • OR
query.filter(or_(User.name == 'ed', User.name == 'sha'))
  • MATCH
query.filter(User.name.match('wendy'))

返回列表和单项(Scalar)


  • all()返回一个列表
>>> 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')>]
  • first()返回至多一个结果,而且以单项形式,而不是只有一个元素的tuple形式返回这个结果.
>>> query.first()
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
  • one()返回且仅返回一个查询结果。当结果的数量不足一个或者多于一个时会报错。
>>> user = query.one()
Traceback (most recent call last):
...
MultipleResultsFound: Multiple rows were found for one()
  • one_or_none():从名称可以看出,当结果数量为0时返回None, 多于1个时报错
  • scalar()和one()类似,但是返回单项而不是tuple

嵌入使用SQL


  • 你可以在Query中通过text()使用SQL语句。例如: 直接将字符串比较写入 filter
>>> from sqlalchemy import text
>>> for user in session.query(User).\
...             filter(text("id<224")).\
...             order_by(text("id")).all():
...     print(user.name)
ed
wendy
mary
fred
  • params()方法来传递参数 params 定义参数 可被text中 调用
sesssion.query(User).filter(text("id<:value and name=:name")).params(value=224, name='shawna').order_by(User.id).one()

<User(name='fred', fullname='Fred Flinstone', password='blah')>
  • 并且,你可以直接使用完整的SQL语句,但是要注意将表名和列明写正确。
>>> session.query(User).from_statement(
...                     text("SELECT * FROM users where name=:name")).\
...                     params(name='ed').all()
[<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>]

计数


Query定义了一个很方便的计数函数count()

>>> session.query(User).filter(User.name.like('%ed')).count()
SELECT count(*) AS count_1
FROM (SELECT users.id AS users_id,
                users.name AS users_name,
                users.fullname AS users_fullname,
                users.password AS users_password
FROM users
WHERE users.name LIKE ?) AS anon_1
('%ed',)
2
  • from sqlalchemy import func
>>> 
from sqlalchemy import funcsession.query(func.count('*')).select_from(User).scalar()
SELECT count(?) AS count_1
FROM users
('*',)
4

阅读文章来自 www.jianshu.com/p/8d085e2f2…