SQLAlchemy ORM教程之二:Query
Query
Session
的query
函数会返回一个Query
对象。query
函数可以接受多种参数类型。可以是类,或者是类的instrumented descriptor。下面的这个例子取出了所有的User
记录。
>>> for instance in session.query(User).order_by(User.id):
... print(instance.name, instance.fullname)
ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone
Query
也接受ORM-instrumented descriptors作为参数。当多个参数传入时,返回结果为以同样顺序排列的tuples
>>> for name, fullname in session.query(User.name, User.fullname):
... print(name, fullname)
ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone
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='Ed Jones'):
... print(name)
ed
>>> for name, in session.query(User.name).\
... filter(User.fullname=='Ed Jones'):
... print(name)
ed
注意Query
对象是generative的,这意味你可以把他们串接起来调用,如下:
>>> for user in session.query(User).\
... filter(User.name=='ed').\
... filter(User.fullname=='Ed Jones'):
... print(user)
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
串接的filter
之间是与的关系。
常用的filter操作符
下面的这些操作符可以应用在filter
函数中
equals
:
query.filter(User.name == 'ed')
not equals
:
query.filter(User.name != 'ed')
LIKE
:
query.filter(User.name.like('%ed%'))
IN
:
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%'))
))
NOT IN
:
query.filter(~User.name.in_(['ed', 'wendy', 'jack']))
IS NULL
:
query.filter(User.name == None)# alternatively, if pep8/linters are a concern
query.filter(User.name.is_(None))
IS NOT NULL
:
query.filter(User.name != None)# alternatively, if pep8/linters are a concern
query.filter(User.name.isnot(None))
AND
:
# 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')
OR
:
from sqlalchemy import or_
query.filter(or_(User.name == 'ed', User.name == 'wendy'))
MATCH
:
query.filter(User.name.match('wendy'))
返回列表(List)和单项(Scalar)
很多Query
的方法执行了SQL命令并返回了取出的数据库结果。
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()
没有查找到结果时:
>>> user = query.filter(User.id == 99).one()
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语句。例如:
>>> 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()
方法来传递参数
>>> session.query(User).filter(text("id<:value and name=:name")).\
... params(value=224, name='fred').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
注意上面我们同时列出了实际的SQL指令。在SQLAlchemy中,我们总是将被计数的查询打包成一个子查询,然后对这个子查询进行计数。即便是最简单的SELECT count(*) FROM table
,也会如此处理。为了更精细的控制计数过程,我们可以采用func.count()
这个函数。
>>> from sqlalchemy import func
SQL>>> session.query(func.count(User.name), User.name).group_by(User.name).all()
SELECT count(users.name) AS count_1, users.name AS users_name
FROM users GROUP BY users.name
()
[(1, u'ed'), (1, u'fred'), (1, u'mary'), (1, u'wendy')]
为了实现最简单的SELECT count(*) FROM table
,我们可以如下调用
>>> session.query(func.count('*')).select_from(User).scalar()
SELECT count(?) AS count_1
FROM users
('*',)
4
如果我们对User
的主键进行计数,那么select_from
也可以省略。
>>> session.query(func.count(User.id)).scalar()
SELECT count(users.id) AS count_1
FROM users
()
4
SQLAlchemy ORM教程之二:Query相关推荐
- 乐鑫代理-启明云端分享ESP32系列教程之二:Linux搭建esp-idf环境
提示:此教程依据乐鑫官方的ESP32入门教程总结而来,仅供个人参考学学习,如有错误,欢迎批评指正.乐鑫官方参考: 乐鑫官方文档地址 1.搭建esp-idf环境 1.1安装虚拟机与Ubuntu 未安装请 ...
- SAP UI5 初学者教程之二:SAP UI5 的引导过程(Bootstrap) 试读版
Jerry 从 2014 年加入 SAP成都研究院 CRM Fiori 开发团队之后开始接触 SAP UI5,曾经在 SAP 社区和"汪子熙"微信公众号上发表过多篇关于 SAP U ...
- 【SAP PO】SAP PO 接口配置完整教程之二REST服务对接
SAP PO 接口配置完整教程之二REST服务对接 1.了解服务协议 1.1.服务通讯协议 1.2.具体接口协议 1.3.接口服务测试 2.PO端接口配置 2.1.PO端ESR配置 2.2.PO端IB ...
- NVIDIA Jetson TX1 系列开发教程之二:刷机与开发前准备
NVIDIA Jetson TX1 系列开发教程之二:刷机与开发前准备 转载请注明作者和出处:http://blog.csdn.net/u011475210 嵌入式平台:NVIDIA Jetson T ...
- github打开前端样式丢失_微信小程序入门教程之二:页面样式
这个系列的上一篇教程,教大家写了一个最简单的 Hello world 微信小程序. 但是,那只是一个裸页面,并不好看.今天接着往下讲,如何为这个页面添加样式,使它看上去更美观,教大家写出实际可以使用的 ...
- image 微信小程序flex_微信小程序入门教程之二:页面样式
这个系列的上一篇教程,教大家写了一个最简单的 Hello world 微信小程序. 但是,那只是一个裸页面,并不好看.今天接着往下讲,如何为这个页面添加样式,使它看上去更美观,教大家写出实际可以使用的 ...
- U-Boot移植教程之二:移植
内容来自 韦东山<嵌入式Linux应用开发完全手册> 一.U-Boot移植 开发板smdk2410的配置适用于大多数S3C2410单板,或是只需要极少的修改即可使用.但是目前U-Boot中 ...
- RabbitMQ系列教程之二:工作队列(Work Queues)
今天开始RabbitMQ教程的第二讲,废话不多说,直接进入话题. (使用.NET 客户端 进行事例演示) 在第一个教程中,我们编写了一个从命名队列中发送和接收消息的程序.在本教程中,我们将创建一个 ...
- cnn 验证集 参与训练吗_一个简单的零基础的机器学习教程之二,字母数字验证码识别...
一.前言 基于前面我发的贴子 土味程序员:一个简单的零基础的机器学习教程,Pytorch搭建Faster R-CNN目标检测平台zhuanlan.zhihu.com 一个非常震撼的目标检测的例子.上 ...
最新文章
- 干货,Wireshark使用技巧-过滤规则
- 29.CSS3边框图片效果
- 二十万字C/C++、嵌入式软开面试题全集宝典五
- MapReduce太慢了,记一次对它的调优建议。
- Java中的三目运算符可能出现的问题
- 如何为部署到 SAP BTP 平台上的 Node.js 应用提供Authorization 和 Trust 管理 - 权限管控
- 数据结构---排序算法的总结
- Android 基础(十三) shape
- python的jieba分词
- php 日期 星期_php日期如何转星期
- 树形背包O(n * v^2)入门
- win10计算机网络共享设置密码,win10局域网设置密码如何设置_win10局域网怎么设置访问密码-win7之家...
- CSS 幻术 | 抗锯齿
- 为markdown目录标题添加序号
- ERP软件是什么意思,买菜大妈讲的通俗易懂
- 投屏类H5应用开发分析
- 微信这几个好用的功能,你该知道
- 微信小程序:小程序内用户帐号登录规范调整和优化建议
- 关于访问 WIN10共享打印机提示 无法连接到打印机的问题
- 利用FastReport传递图片参数,在报表上展示签名信息
热门文章
- 精选| 2021年2月R新包推荐(第51期)
- 一个函数统一238个机器学习R包,这也太赞了吧
- GEO2R/GEOquery的结果可能是错的!!!
- M1芯片Mac也可以安装Windows系统啦 使用PD16虚拟机安装ARM版Windows10教程
- java immutable系列_Java Immutable类代码示例
- 信息学奥赛一本通 提高篇 第六部分 数学基础 第1章 快速幂
- python程序可以在任何安装了解释器_Python解释器新手安装教程
- 计算机网络-VRRP
- Java工作笔记-生成及解析Json字符串
- Qt + Python + OpenCV图标替换工具 之 项目介绍(一)