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

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
(0)

相关推荐

  • Python的ORM框架SQLAlchemy入门教程

    SQLAlchemy的理念是,SQL数据库的量级和性能重要于对象集合:而对象集合的抽象又重要于表和行. 一 安装 SQLAlchemy 复制代码 代码如下: pip install sqlalchemy 导入如果没有报错则安装成功 复制代码 代码如下: >>> import sqlalchemy>>> sqlalchemy.__version__'0.9.1'>>> 二 使用 sqlalchemy对数据库操作 1. 定义元信息,绑定到引擎 复制代码 代

  • Python ORM框架SQLAlchemy学习笔记之数据查询实例

    前期我们做了充足的准备工作,现在该是关键内容之一查询了,当然前面的文章中或多或少的穿插了些有关查询的东西,比如一个查询(Query)对象就是通过Session会话的query()方法获取的,需要注意的是这个方法的参数数目是可变的,也就是说我们可以传入任意多的参数数目,参数的类型可以是任意的类组合或者是类的名称,接下来我们的例子就说明了这一点,我们让Query对象加载了User实例. 复制代码 代码如下: >>> for instance in session.query(User).or

  • 研究Python的ORM框架中的SQLAlchemy库的映射关系

    前面介绍了关于用户账户的User表,但是现实生活中随着问题的复杂化数据库存储的数据不可能这么简单,让我们设想有另外一张表,这张表和User有联系,也能够被映射和查询,那么这张表可以存储关联某一账户的任意数量的电子邮件地址.这种联系在数据库理论中是典型的1-N (一对多)关系,用户表某一用户对应N条电子邮件记录. 之前我们的用户表称为users,现在我们再建立一张被称为addresses的表用于存储电子邮件地址,通过Declarative系统,我们可以直接用映射类Address来定义这张表: >>

  • Python的Flask框架中SQLAlchemy使用时的乱码问题解决

    一.问题 这两天在学习使用flask + SQLAlchemy 定制一个web查询页面的demo ,在测试时,发现查询到的结果显示乱码 .这里将解决方法记录下. 二.解决思路 1.flask 程序上定位 flask的文档中提到可以通过设置SQLALCHEMY_NATIVE_UNICODE来禁止使用SQLAlchemy默认的Unicode编码.有可能是SQLAlchemy默认的Unicode编码不是UTF-8,抱着这样的想法,在程序中指定了"SQLALCHEMY_NATIVE_UNICODE=Fa

  • 编写Python脚本把sqlAlchemy对象转换成dict的教程

    在用sqlAlchemy写web应用的时候,经常会用json进行通信,跟json最接近的对象就是dict,有时候操作dict也会比操作ORM对象更为方便,毕竟不用管数据库session的状态了. 假设数据库里有一张post表,其中一种方法就是 p = session.query(Post).first() p.__dict__ 但由于p是sqlAlchemy的对象,所以p.__dict__中会有一些其他的属性比如_sa_instance这种我们不需要关注的 那么我们可以给model的基类加一个方

  • Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍

    1. 添加一个新对象 前面介绍了映射到实体表的映射类User,如果我们想将其持久化(Persist),那么就需要将这个由User类建立的对象实例添加到我们先前创建的Session会话实例中: 复制代码 代码如下: ed_user = User('ed', 'Ed Jones', 'edspassword')session.add(ed_user) 上面两段代码执行完后对象持久化了么?你或许会兴冲冲的跑去数据库里查看,结果却失望而归--数据库里什么都没有.为什么呢?因为SQLAlchemy采取的是

  • 教大家使用Python SqlAlchemy

    本文实例解析Python SqlAlchemy的使用方法,分享给大家供大家参考,具体内容如下 1.初始化连接 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine('mysql://pass@localhost/test'echo=True) DBSession = sessionmaker(bind=engine) session = DBSessi

  • Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例

    最近正好在寻求一种Python的数据库ORM (Object Relational Mapper),SQLAlchemy (项目主页)这个开源项目进入了我的视线,本来想尝试着使用Django的ORM模块的,无奈Django的模块联系比较紧密,没能单独分拆下来,一定程度上说明Django自成体系的生态系统在给我们带来快速便捷的开发环境的同时牺牲了组装的灵活性. 初次学习,也没实质感觉到SQLAlchemy的好处,不过看其介绍的很多大公司均采用该项目,而且其支持的数据库还是蛮丰富的,所以我觉得花点时

  • Python的Django框架中使用SQLAlchemy操作数据库的教程

    零.SQLAlchemy是什么? SQLAlchemy的官网上写着它的介绍文字: SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL. SQLAlchemy 是一个非常强大的ORM和数据库工具,但是它庞大的文档和复杂的功能总是让很 多人望而生畏.而Django的ORM相对来说

  • Python的SQLAlchemy框架使用入门

    数据库表是一个二维表,包含多行多列.把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含id和name的user表: [ ('1', 'Michael'), ('2', 'Bob'), ('3', 'Adam') ] Python的DB-API返回的数据结构就是像上面这样表示的. 但是用tuple表示一行很难看出表的结构.如果把一个tuple用class实例来表示,就可以更容易地看出表的结构来: class U

  • Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍

    1. 创建映射类的实例(Instance) 前面介绍了如何将数据库实体表映射到Python类上,下面我们可以创建这个类的一个实例(Instance),我们还是以前一篇文章的User类为例,让我们创建User对象: 复制代码 代码如下: >>> ed_user = User('ed', 'Ed Jones', 'edspassword')>>> ed_user.name'ed'>>> ed_user.password'edspassword'>&g

  • 在Python的Flask框架下使用sqlalchemy库的简单教程

    flask中的sqlalchemy 相比于sqlalchemy封装的更加彻底一些 , 在一些方法上更简单 首先import类库: 在CODE上查看代码片派生到我的代码片 <span style="font-size:18px;">from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy</span> 然后,需要加载 数据库路径 在CODE上查看代码片派生到我的代码片 <span

  • Python程序中使用SQLAlchemy时出现乱码的解决方案

    今天对clubot进行了升级, 但是导入数据后中文乱码, 一开是找资料说是在创建引擎的时候添加编码信息: engine = create_engine("mysql://root:@localhost:3306/clubot?charset=utf8") 但是这并不行, 然后查看表信息: > show create table clubot_members; clubot_members | CREATE TABLE `clubot_members` ( `id` int(11)

  • Python ORM框架SQLAlchemy学习笔记之关系映射实例

    昨天简单介绍了SQLAlchemy的使用,但是没有能够涉及其最精彩的ORM部分,今天我将简单说明一下,当然主要还是讲解官方文档的内容,由于是学习笔记,有可能存在精简或者自己理解的部分,不做权威依据. 当我们开始使用ORM,一种可配置的结构可以用于描述我们的数据库表,稍后我们定义的类将会被映射到这些表上.当然现代的SQLAlchemy(新版本SQLAlchemy,原文是modern SQLAlchemy)使用Declarative把这两件事一起做了,即允许我们把创建类和描述定义数据库表以及它们之间

  • Python SQLAlchemy基本操作和常用技巧(包含大量实例,非常好)

    首先说下,由于最新的 0.8 版还是开发版本,因此我使用的是 0.79 版,API 也许会有些不同.因为我是搭配 MySQL InnoDB 使用,所以使用其他数据库的也不能完全照搬本文. 接着就从安装开始介绍吧,以 Debian/Ubuntu 为例(请确保有管理员权限):1.MySQL 复制代码 代码如下: apt-get install mysql-serverapt-get install mysql-clientapt-get install libmysqlclient15-dev 2.

随机推荐