当前位置:   article > 正文

sqlalchemy系列教程二-query对象_sqlalchemy.orm.exc.noresultfound: no row was found

sqlalchemy.orm.exc.noresultfound: no row was found for one()
sqlalchemy系列教程二

介绍一下 Query 对象的使用

https://docs.sqlalchemy.org/en/latest/orm/tutorial.html#querying

  • 首先看一下例子
    query 可以过滤属性
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Time    : 2018/11/12 19:09
@File    : query_data2.py
@Author  : frank.chang@shoufuyou.com


query 对象 介绍

"""
from base import session
from model.creat_table import TUser


if __name__ == '__main__':

    for instance in session.query(TUser).filter_by(name='frank25'):
        print(instance)
        print(instance.name, instance.mobile)

    for item in session.query(TUser.name,TUser.id).filter_by(name='frank25'):
        print(item)
        print(item.id,item.name)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

结果如下:

<User(id='26', name='frank25', mobile='1234921325', password='edspassword25')>
frank25 1234921325
('frank25', 26)
26 frank25
  • 1
  • 2
  • 3
  • 4

query 里面可以过滤需要的字段,类似select 要选取的字段, 如果 query() 里面参数是类名,则返回所有字段.返回一个instance,
如果过滤字段的话, 需要跟上具体的字段. 当然 这时候返回是一个 ResultProxy.
也可以用 .name 去访问字段.

总结一下 query 里面 可以传入 类名.属性名, 来筛选 想要的字段.

来看下 first ,all one 的区别
saclar 是什么?

first

Return the first result of this Query or None if the result doesn’t contain any row.

first 如果没有结果, 返回为None, 如果有结果只返回第一条结果.这个方法不会往外抛异常。

all

This results in an execution of the underlying query.
all 会返回一个list

one

如果查询的结果是唯一的,可以用one , 如果用one,结果数据里面有多个或者没有都会报错.
会抛出异常 MultipleResultsFound , NoResultFound
这种我感觉适合主键的查询,比如说 id 的查询

one_or_none

如果查询结果是唯一的或者没有 可以用这个, 如果结果集有多个, 同样也会报错.
这个和one 的区别是,如果查询没有的情况下,返回None. 如果有的话,结果集必须是一个.
如果 有多个结果集 也会抛异常 MultipleResultsFound

scalar

这个感觉和first 比较像,也是返回第一个结果集,但是稍微有一点区别,这个查询如果
如果有多个也会抛异常。 而first 这个方法是不会往外抛异常的。

“”“Return the first element of the first result or None
if no rows present. If multiple rows are returned,
raises MultipleResultsFound.
“””

  • 看下 first 和all
if __name__ == '__main__':
    result = session.query(TUser).filter_by(name='frank5').all()
    print("type(result):{}".format(type(result)))
    for user in result:
        print(user)

    print("###" * 28)
    result = session.query(TUser).filter_by(name='frank5').first()

    print(result)

    # 数据库里面没有name=frank5_ABC
    result = session.query(TUser).filter_by(name='frank5_ABC').first()
    print(result)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
结果如下:
/Users/frank/.local/share/virtualenvs/mysqlalchemy-demo-0htClb7e/bin/python /Users/frank/PycharmProjects/mysqlalchemy-demo/query_data2.py
type(result):<class 'list'>
<User(id='6', name='frank5', mobile='123492135', password='edspassword5')>
<User(id='36', name='frank5', mobile='123492135', password='edspassword5')>
<User(id='46', name='frank5', mobile='123492135', password='edspassword5')>
####################################################################################
<User(id='6', name='frank5', mobile='123492135', password='edspassword5')>
None

Process finished with exit code 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • first , one , one_or_none 的区别
    # 数据库里面没有数据
    result = session.query(TUser).filter_by(id=100).one()
    print(result)
  • 1
  • 2
  • 3

错误如下:

sqlalchemy.orm.exc.NoResultFound: No row was found for one()

    result = session.query(TUser).filter_by(id=100).one_or_none()
    print(result)  # None 

  • 1
  • 2
  • 3

如果查询结果集有多条记录,会抛异常 MultipleResultsFound

    # 数据库里面有多条 name=frank5 的记录
    result = session.query(TUser).filter_by(name='frank5').one_or_none()
    print(result)
    
  • 1
  • 2
  • 3
  • 4

错误如下:

sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one_or_none()

其实看下实现:


    def one_or_none(self):
        """Return at most one result or raise an exception.

        Returns ``None`` if the query selects
        no rows.  Raises ``sqlalchemy.orm.exc.MultipleResultsFound``
        if multiple object identities are returned, or if multiple
        rows are returned for a query that returns only scalar values
        as opposed to full identity-mapped entities.

        Calling :meth:`.Query.one_or_none` results in an execution of the
        underlying query.

        .. versionadded:: 1.0.9

            Added :meth:`.Query.one_or_none`

        .. seealso::

            :meth:`.Query.first`

            :meth:`.Query.one`

        """
        ret = list(self)

        l = len(ret)
        if l == 1:
            return ret[0]
        elif l == 0:
            return None
        else:
            raise orm_exc.MultipleResultsFound(
                "Multiple rows were found for one_or_none()")

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

首先把query 对象迭代一下, 拿到list 之后看list 的长度, 如果大于1,直接抛异常.
总结一下: one 用来查询仅有一条的记录, one_or_none 取仅有一条记录或者没有的记录。
first 用来查询记录中的第一条记录,如果没有记录,直接返回None.这个是不会抛异常的。

  1. scalar 和first ,one有什么区别呢?

首先first 是取结果集中第一个结果,如果结果集没有则返回None,不会抛出异常的

one 结果集中有且仅有一个结果集,否则会抛异常出来 MultipleResultsFound,NoResultFound

而 salar 首先去掉one,如果,如果one 抛出NoResultFound异常, 则scalar 会返回一个空值,如果抛出MultipleResultsFound ,scalar 这个方法也会往外抛出这个异常。


def test_diff(myid):
    result = session.query(TUser).filter(TUser.id == myid).scalar()
    print('scalar result:')
    print(result)

    result2 = session.query(TUser).filter(TUser.id == myid).first()
    print('first result:')

    print(result2)
    

test_diff(10)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

对于取id 操作,结果要么是有,要么没有。所以这样看起来结果是一样的。
结果如下:

scalar result:
<User(id='10', name='frank9', mobile='123492139', password='edspassword9')>
first result:
<User(id='10', name='frank9', mobile='123492139', password='edspassword9')>

  • 1
  • 2
  • 3
  • 4
  • 5

如果filter 里面可以过滤多个结果集,scalar 就会报错了。

def test_diff_name(name):

    result2 = session.query(TUser).filter(TUser.name == name).first()
    print('first result:')
    print(result2)


    result = session.query(TUser).filter(TUser.name == name).scalar()
    print('scalar result:')
    print(result)




test_diff_name('frank1')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

结果如下,first可以成功取出一条,scalar 就会抛异常出来,MultipleResultsFound

first result:
<User(id='2', name='frank1', mobile='123492131', password='edspassword1')>
Traceback (most recent call last):
  File "/Users/frank/.local/share/virtualenvs/mysqlalchemy-demo-0htClb7e/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2954, in one
    ret = self.one_or_none()
  File "/Users/frank/.local/share/virtualenvs/mysqlalchemy-demo-0htClb7e/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2933, in one_or_none
    "Multiple rows were found for one_or_none()")
sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one_or_none()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

自我感觉 scalar 这个 函数有点鸡肋,本身 scalar 是调用 self.one() 方法,然后只是对没有结果的异常捕获了一下,然后返回None 值,对于MultipleResultsFound也是直接往外抛异常。

下面是 scalar 的实现代码

class Query:

    def scalar(self):
        try:
            ret = self.one()
            if not isinstance(ret, tuple):
                return ret
            return ret[0]
        except orm_exc.NoResultFound:
            return None
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

  • 排序操作

sqlalchemy 排序操作也很方便

1.可以直接导入这个包,进行操作

from sqlalchemy import asc, desc

if __name__ == '__main__':
    query = session.query(TUser).order_by(desc(TUser.id)).limit(5)
    print(query)
    for ret in query:
        print(ret)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

直接用函数 desc 降序排序, asc 升序排序 ,order_by 后面 跟上要排序的字段就可以 了。

  1. 第二种方式
    ordery_by() 直接字段名称后面 跟上 asc() , desc()
if __name__ == '__main__':
    query = session.query(TUser).order_by(TUser.id.asc()).limit(5)

    for ret in query:
        print(ret)
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:

<User(id='1', name='frank0', mobile='123492130', password='edspassword0')>
<User(id='2', name='frank1', mobile='123492131', password='edspassword1')>
<User(id='3', name='frank2', mobile='123492132', password='edspassword2')>
<User(id='4', name='frank3', mobile='123492133', password='edspassword3')>
<User(id='5', name='frank4', mobile='123492134', password='edspassword4')>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 组合查询
    and or_ 的使用

1.and的使用

if __name__ == '__main__':

    query = session.query(TUser).filter_by(name='frank3')

    for user in query:
        print(user)

    print('---' * 30)

    query = session.query(TUser).filter_by(name='frank3', id=34)
    print(query)
    r = query.all()
    print(r)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

结果如下:

<User(id='4', name='frank3', mobile='123492133', password='edspassword3')>
<User(id='34', name='frank3', mobile='123492133', password='edspassword3')>
<User(id='44', name='frank3', mobile='123492133', password='edspassword3')>
------------------------------------------------------------------------------------------
SELECT `TUser`.create_time AS `TUser_create_time`, `TUser`.id AS `TUser_id`, `TUser`.name AS `TUser_name`, `TUser`.mobile AS `TUser_mobile`, `TUser`.password AS `TUser_password` 
FROM `TUser` 
WHERE `TUser`.name = %(name_1)s AND `TUser`.id = %(id_1)s
[<User(id='34', name='frank3', mobile='123492133', password='edspassword3')>]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

createing-a-session
query

  1. or 的使用
if __name__ == '__main__':

    # Query
    query = session.query(TUser).filter(or_(TUser.name == 'frank1', TUser.name == 'frank29'))
    print(query)
    result = query.all()

    for ret in result:
        print(ret)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

结果如下:query 打印出来sql 语句是用or 来查询

SELECT `TUser`.create_time AS `TUser_create_time`, `TUser`.id AS `TUser_id`, `TUser`.name AS `TUser_name`, `TUser`.mobile AS `TUser_mobile`, `TUser`.password AS `TUser_password` 
FROM `TUser` 
WHERE `TUser`.name = %(name_1)s OR `TUser`.name = %(name_2)s
<User(id='2', name='frank1', mobile='123492131', password='edspassword1')>
<User(id='30', name='frank29', mobile='1234921329', password='edspassword29')>
<User(id='32', name='frank1', mobile='123492131', password='edspassword1')>
<User(id='42', name='frank1', mobile='123492131', password='edspassword1')>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
总结

本文介绍了Query 的常用方法,first,all ,one 等以及之间的区别,介绍排序如何使用,筛选属性
联合查询 and, or_ 的用法。当然还有很多没有提及,可以看下官方文档,都有详细的介绍。

Query 对象有很多的用法,官方文档都有给出例子, 有时间的时候 ,多查询官方文档吧。

  • 参考文档

https://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.one

https://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.one_or_none

https://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.first

https://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.get

https://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.all

分享快乐,留住感动.2018-11-17 10:25:53 --frank
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/613307
推荐阅读
相关标签
  

闽ICP备14008679号