Python的ORM框架中SQLAlchemy库的查询操作的教程


Posted in Python onApril 25, 2015

1. 返回列表和标量(Scalar)

前面我们注意到Query对象可以返回可迭代的值(iterator value),然后我们可以通过for in来查询。不过Query对象的all()、one()以及first()方法将返回非迭代值(non-iterator value),比如说all()返回的是一个列表:

>>> query = session.query(User).\
>>>     filter(User.name.like('%ed')).order_by(User.id)
>>> query.all() 
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 ? ORDER BY users.id
('%ed',)
 
[User('ed','Ed Jones', 'f8s7ccs'), User('fred','Fred Flinstone', 'blah')]

first()方法限制并仅作为标量返回结果集的第一条记录:

>>> query.first() 
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 ? ORDER BY users.id
 LIMIT ? OFFSET ?
('%ed', 1, 0)
 
<User('ed','Ed Jones', 'f8s7ccs')>

one()方法,完整的提取所有的记录行,并且如果没有明确的一条记录行(没有找到这条记录)或者结果中存在多条记录行,将会引发错误异常NoResultFound或者MultipleResultsFound:

>>> from sqlalchemy.orm.exc import MultipleResultsFound
>>> try: 
...   user = query.one()
... except MultipleResultsFound, e:
...   print e
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 ? ORDER BY users.id
('%ed',)
 
Multiple rows were found for one()

>>> from sqlalchemy.orm.exc import NoResultFound
>>> try: 
...   user = query.filter(User.id == 99).one()
... except NoResultFound, e:
...   print e
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 ? AND users.id = ? ORDER BY users.id
('%ed', 99)
 
No row was found for one()

2. 使用原义SQL (Literal SQL)

Query对象能够灵活的使用原义SQL查询字符串作为查询参数,比如我们之前用过的filter()和order_by()方法:

>>> for user in session.query(User).\
...       filter("id<224").\
...       order_by("id").all(): 
...   print user.name
SELECT users.id AS users_id,
    users.name AS users_name,
    users.fullname AS users_fullname,
    users.password AS users_password
FROM users
WHERE id<224 ORDER BY id
()
 
ed
wendy
mary
fred

当然很多人可能会和我感觉一样,会有些不适应,因为使用ORM就是为了摆脱SQL语句的,没想到现在又看到SQL的影子了。呵呵,SQLAlchemy也要照顾到使用上的灵活性嘛,毕竟有些查询语句直接编入要容易得多。

当然绑定参数也可以用基于字符串的SQL指派,使用冒号来标记替代参数,然后再使用params()方法指定相应的值:

>>> session.query(User).filter("id<:value and name=:name").\
...   params(value=224, name='fred').order_by(User.id).one() 
SELECT users.id AS users_id,
    users.name AS users_name,
    users.fullname AS users_fullname,
    users.password AS users_password
FROM users
WHERE id<User('fred','Fred Flinstone', 'blah')>

到这里,SQL语句的样子已经初见端倪了,其实我们可以更极端一点,直接使用SQL语句,什么?这样就失去ORM的价值了!别急,这里只是介绍一下支持这种用法,当然我建议不到万不得已,尽量不要这样写,因为可能会有兼容的问题,毕竟各个数据库的SQL方言不一样。不过有一点需要注意的是,如果要直接使用原生SQL语句,在被query()所查询的映射类中,你必须保证语句所指代的列仍然被映射类所管理,比如接下来的例子:

>>> session.query(User).from_statement(
...           "SELECT * FROM users where name=:name").\
...           params(name='ed').all()
SELECT * FROM users where name=?
('ed',)
 
[<User('ed','Ed Jones', 'f8s7ccs')>]

我们还可以在query()中直接使用列名来指派我们想要的列而摆脱映射类的束缚:

>>> session.query("id", "name", "thenumber12").\
...     from_statement("SELECT id, name, 12 as "
...         "thenumber12 FROM users where name=:name").\
...         params(name='ed').all()
SELECT id, name, 12 as thenumber12 FROM users where name=?
('ed',)
 
[(1, u'ed', 12)]

3. 计数 (Counting)

对于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

count()方法被用于确定返回的结果集中有多少行,让我们观察一下产生的SQL语句,SQLAlchemy先是取出符合条件的所有行集合,然后再通过SELECT count(*)来统计有多少行。当然有点SQL知识的同学可能知道这条语句可以以更精简的方式写出来,比如SELECT count(*) FROM table,当然现代版本的SQLAlchemy不会去揣摩这样的想法。

假使我们要让查询语句更加精炼或者要明确要统计的列,我们可以通过表达式func.count()直接使用count函数,比如下面的例子介绍统计并返回每个唯一的用户名字:

>>> from sqlalchemy import func
>>> 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
Python 相关文章推荐
python处理文本文件并生成指定格式的文件
Jul 31 Python
使用Python写CUDA程序的方法
Mar 27 Python
Python实现将Excel转换成xml的方法示例
Aug 25 Python
用Pycharm实现鼠标滚轮控制字体大小的方法
Jan 15 Python
利用python计算windows全盘文件md5值的脚本
Jul 27 Python
Python中调用其他程序的方式详解
Aug 06 Python
Python 实现try重新执行
Dec 21 Python
解决ROC曲线画出来只有一个点的问题
Feb 28 Python
总结Pyinstaller的坑及终极解决方法(小结)
Sep 21 Python
Selenium环境变量配置(火狐浏览器)及验证实现
Dec 07 Python
python 利用matplotlib在3D空间中绘制平面的案例
Feb 06 Python
python神经网络Xception模型
May 06 Python
Python实现单词拼写检查
Apr 25 #Python
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
Apr 25 #Python
使用PDB简单调试Python程序简明指南
Apr 25 #Python
Python脚本判断 Linux 是否运行在虚拟机上
Apr 25 #Python
在Python中使用cookielib和urllib2配合PyQuery抓取网页信息
Apr 25 #Python
使用Python的Tornado框架实现一个一对一聊天的程序
Apr 25 #Python
使用Python发送邮件附件以定时备份MySQL的教程
Apr 25 #Python
You might like
一个目录遍历函数
2006/10/09 PHP
PHP取余函数介绍MOD(x,y)与x%y
2014/05/15 PHP
PHP调试的强悍利器之PHPDBG
2016/02/22 PHP
Javascript读取cookie函数代码
2010/10/16 Javascript
js怎么覆盖原有方法实现重写
2014/09/04 Javascript
javascript基本包装类型介绍
2015/04/10 Javascript
用Node.js通过sitemap.xml批量抓取美女图片
2015/05/28 Javascript
JavaScript获取css行间样式,内连样式和外链样式的简单方法
2016/07/18 Javascript
基于JavaScript实现在新的tab页打开url
2016/08/04 Javascript
深入理解AngularJS中的ng-bind-html指令和$sce服务
2016/09/08 Javascript
前端js实现文件的断点续传 后端PHP文件接收
2016/10/14 Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
2016/10/24 Javascript
Node.js利用Net模块实现多人命令行聊天室的方法
2016/12/23 Javascript
$.browser.msie 为空或不是对象问题的多种解决方法
2017/03/19 Javascript
jQuery封装placeholder效果实现方法,让低版本浏览器支持该效果
2017/07/08 jQuery
JS中call和apply函数用法实例分析
2018/06/20 Javascript
微信小程序上传多图到服务器并获取返回的路径
2019/05/05 Javascript
js实现从右往左匀速显示图片(无缝轮播)
2020/06/29 Javascript
[52:10]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第二场 6.3
2018/06/04 DOTA
[01:20:06]TNC vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python2.x中文乱码问题解决方法
2015/06/02 Python
Django 实现下载文件功能的示例
2018/03/06 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
2018/05/16 Python
使用python itchat包爬取微信好友头像形成矩形头像集的方法
2019/02/21 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
2019/08/08 Python
python实现tail实时查看服务器日志示例
2019/12/24 Python
pycharm运行程序时看不到任何结果显示的解决
2020/02/21 Python
Python基于DB-API操作MySQL数据库过程解析
2020/04/23 Python
简述 Python 的类和对象
2020/08/21 Python
pycharm 代码自动补全的实现方法(图文)
2020/09/18 Python
python 无损批量压缩图片(支持保留图片信息)的示例
2020/09/22 Python
简洁自适应404页面HTML好看的404源码
2020/12/16 HTML / CSS
初中三年学生的学习自我评价
2013/11/13 职场文书
个人汇报材料范文
2014/12/30 职场文书
2015年技术工作总结范文
2015/04/20 职场文书
如何撰写创业策划书
2019/06/27 职场文书