Python SQLAlchemy --2

本文為 Python SQLAlchemy ORM 一系列教學文:

接下來會更深入地探討查詢的使用。

查詢的基本使用法為 session.query(Mapped Class),其後可加 .group_by(), .order_by(), .delete 等方法。

只是要注意的是 query() 接受的參數為 Mapped Class (例如先前定義的 User 類別),而不是表格名稱。

例如在 範例 2 中是以 User 做為參數,而不是以 user 這個表格名稱做為參數。

如果查詢成功就會回傳 Query Object,若無則會回傳 None 。

首先,query() 可以使用 from_statement() 方法,直接以完整的 SQL 指令進行查詢,更可以搭配 params() 將變數代入 SQL 指令中。

例如:

123
rows = session.query(User).from_statement(‘SELECT * FROM user WHERE name=:name‘).params(name=‘user1‘)for r in rows:    print(r.id)

其中,上述 SQL 指令中的 :name 代表會有一個參數名 name ,然後在 params(name=‘user1‘) 中就指明了 name 的值為 user1 。

基本上這樣就能夠進行大多數的查詢,但若希望能夠更深入地學會運用 SQLAlchemy 進行查詢,就可以閱讀以下的文章。

以下是幾個關於 query() 的使用範例(由於 User 類別已在先前已經定義過了,因此以下範例會直接省略)。

SELECT

範例的 SQL 指令 ─ SELECT * FROM user

123
for r in session.query(User):    print(type(r))    print(r.name, r.username, r.password)

執行結果如下:

12
[class main__.user]1 user1 username1 3833b3a1c69cf71a31d86cb5bb4d3866789b4d1e

上述的範例程式碼,是列出每一列 SELECT 查詢出來的結果,可以注意到的是每一列的 r 都是一個 User 實例,因此我們就可以依照先前定義 User 類別的欄位屬性,將這些屬性列印出來。

SELECT user.name FROM user query() 也能針對個別欄位進行 SELECT ,只要將 Mapped Class 及其屬性做為參數即可,例如只想查詢全部的 username ,那麼 query() 的參數就會是 User.username

123
for r in session.query(User.username):    print(type(r))    print(r.username)

執行結果如下:

12
[class sqlalchemy.util._collections.keyedtuple]username1

此處值得注意的是,當有只針對個別欄位 SELECT 的情況時,就是回傳 KeyedTuple 實例了,而不是我們先前的定義的 User 類別的實例。

WHERE

範例 SQL 指令 ─ SELECT * FROM user WHER id = 1

若要使用 WHERE 條件查詢,則是使用 filter_by()filter() 方法。

兩者的差異在於 filter_by() 必須使用屬性名稱做為參數名稱,然後加上查詢條件。例如查詢 id 為 1 的資料為 filter_by(id=1)。\

filter() 則是以 Mapped Class 及其屬性加上查詢條件做為參數,而且支援 Python 運算子。例如同樣查詢 id 為 1 的資料為 filter(User.id == 1)

不過,SQLAlchemy 其實也有提供 filter() 以字串為參數的用法,例如查詢 id 為 1 也可以表示成為 filter(id=1)

此外,多個查詢條件可以用附加 .filter(…) 的形式達成。

123456
for r in session.query(User.id).filter_by(id=1):    print(r.id)

# 多個查詢條件for r in session.query(User.id).filter(User.id==1).filter(User.name==‘user1‘):    print(r.id)

更多的查詢條件可以看 Common Filter Operators ,如 LIKE, IN, NOT IN 等等。

ORDER BY

範例 SQL 指令 ─ SELECT user.id FROM user ORDER BY user.id DESC

排序可以使用 order_by() ,參數為 Mapped Class 及其屬性。例如想依照 id 欄位排序,那麼參數就會是 User.id 。此外, 預設的排序為遞增排序

遞減排序的部份則要記得 import desc 模組:

1
from sqlalchemy import desc

以下範例示範遞增及遞減排序:

123456789
# 遞減for r in session.query(User.id).order_by(User.id.desc()):    print(type(r))    print(r.id))

# 遞增for r in session.query(User.id).order_by(User.id.asc()):    print(type(r))    print(r.id)

LIMIT

有時會需要使用 LIMIT 來限制查詢的範圍,例如分頁功能,最直接的方法就是用 Python slice 的功能,SQLAlchemy 就會自動將 LIMIT 的查詢條件附加到查詢的 SQL 語法後面。

範例:

12
for row in session.query(User)[500:520]:    print(row.id)

如上述加上 [500:520] ,就能夠看到 SQLAlchemy 的查詢指令多了 LIMIT ? OFFSET ? 的訊息。

其中 520 減 500 的數值為 LIMIT 的數值,限制 20 筆;而 500 為 OFFSET 從第 500 筆資料開始查詢。

GROUP BY

範例 SQL 指令 ─ SELECT * FROM user GROUP BY user.name

如果要使用 GROUP BY,則是使用 group_by()

12
for r in session.query(User).group_by(User.name):    print(r.name)

HAVING

範例 SQL 指令 ─ SELECT user.name FROM user GROUP BY user.name HAVING count(user.id) > 2

與 GROUP BY 常一起使用的通常會有 HAVING , COUNT() , SUM() , MAX() … 等語法。

在 SQLAlchemy 中 HAVING 是接在 group_by() 後的 having()方法,而 COUNT(), SUM(), MAX() 等函數則是由 SQLAlchemy 的 func 模組所實作,因此要使用 COUNT() , SUM() , MAX() 等函數須先 import func 模組。

1
from sqlalchemy import func

以下是結合 HAVING 及 COUNT() 的範例,用來列印出資料表內相同名字大於 2 個以上使用者名稱:

12
for row in session.query(User).group_by(User.name).having(func.count(User.id) > 2):    print(row.name)

Alias(AS)

範例 SQL 指令 ─ SELECT u.id FROM user AS u

表格的 AS 別名用法是使用 aliasd() 方法,可以將 Mapped Class 及表格名稱以別名進行查詢。

此一方法需要 import aliasd 模組。

1
from sqlalchemy.orm import aliased

表格名稱別名範例:

123
user_alias = aliased(User, name=‘user_alias‘)for row in session.query(user_alias):    print(row.name)

如果成功,應該會看到 SELECT 的過程多了FROM user AS user_alias 的訊息出現,如下所示。

12
2013-08-25 11:52:45,177 INFO sqlalchemy.engine.base.Engine SELECT user_alias.id AS user_alias_id, user_alias.name AS user_alias_name, user_alias.username AS user_alias_username, user_alias.password AS user_alias_passwordFROM user AS user_alias

此外,欄位名稱也能夠使用 AS 的 SQL 語法,不過在 SQLAlchemy 中則是用 label() 來命名。

範例如下:

12
for row in session.query(User.name.label(‘n‘)):    print(row.n)

計算查詢結果筆數

如要計算查詢結果筆數,使用 count() 即可。

例如:

123
print(    session.query(User).group_by(User.name).having(func.count(User.id) > 2).count())

注意:此處的 count()func.count() 不同

first, scalar(), one(), all()

除了查詢結果筆數之外,SQLAlchemy 也提供了一些方便的方法確認查詢結果或回傳查詢結果。

first() 只回傳第一筆結果,即使有多筆結果也只會回傳第一筆

scalar() 只回傳第一筆結果,查無結果則回傳 None ,若有查詢有多筆結果則會產生例外錯誤

scalar() 範例如下:

123456789
try:    result = session.query(User).scalar()except sqlalchemy.orm.exc.MultipleResultsFound:    print(‘MultipleResultsFound!‘)else:    if result is None:        print(‘NoResultFound!‘)    else:        print(result.id)

one() 回傳一筆結果,如有多筆或查無結果的情況則會產生例外錯誤

one() 範例:

12345678
try:    result = session.query(User).one()except sqlalchemy.orm.exc.NoResultFound:    print(‘NoResultFound!‘)except sqlalchemy.orm.exc.MultipleResultsFound:    print(‘MultipleResultsFound!‘)else:    print(result.id)

all() 將所有結果匯出成一個 list 回傳

all() 範例:

123
allres = session.query(User).all()for r in allres:    print(r.id)

參考資料:

http://docs.sqlalchemy.org/en/latest/

时间: 2024-08-05 10:51:35

Python SQLAlchemy --2的相关文章

Python SQLAlchemy --1

本文為 Python SQLAlchemy ORM 一系列教學文: SQLAlchemy 大概是目前 Python 最完整的資料庫操作的套件了,不過最令人垢病的是它的文件真的很難閱讀,如果不搭配個實例進行學習真的很難理解. 此外,SQLAlchemy 依照架構將文件說明分為 SQLAlchemy ORM 與 SQLAlchemy Core ,如果不去細究到底有何不同,很容易讓人誤解. 基本上,如果只是基本的資料庫的表格建立.查詢.更新.刪除等,比較不需要使用表格間的關聯以及表格與 Python

python SQLAlchemy

这里我们记录几个python SQLAlchemy的使用例子: 如何对一个字段进行自增操作 user = session.query(User).with_lockmode('update').get(1)user.age += 1session.commit() 对多条数据进行删除操作: session.query(User).filter(or_(User.id == 1, User.id == 2, User.id == 3)).delete() 各种连接表,并进行多表操作: from s

Python SqlAlchemy使用方法

Python SqlAlchemy使用方法 1.初始化连接 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine('mysql://[email protected]/test'echo=True) DBSession = sessionmaker(bind=engine) session = DBSession() ret=session.execu

记一个python+sqlalchemy+tornado的一个高并发下,产生重复记录的bug

场景:在用户通过支付通道支付完成返回时,发现我收到的处理数据记录中有两条同样的数据记录, 也就是同一笔钱,我数据库中记为了两条一样的记录. tornado端代码 from tornado import gen from tornado.concurrent import run_on_executor class processNetPay(BaseHandler): '''处理指定订单,指定支付请求,返回处理结果 ' 返回包含订单信息与用户信息体 ''' @tornado.web.asynch

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

http://www.makaidong.com/%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6/28053.shtml "Python SQLAlchemy基本操作和常用技巧包含大量实例,非常好python":关键词:python sqlalchemy 基本 操 作和 常用 技巧 包含 大量 实例 非常好 python 首先说下,由于最新的 0.8 版还是开发版本,因此我使用的是 0.79 版,api 也许会有些不同.因为我是搭配 mysql innodb

Python SQLAlchemy入门教程

本文将以Mysql举例,介绍sqlalchemy的基本用法.其中,Python版本为2.7,sqlalchemy版本为1.1.6. 一. 介绍 SQLAlchemy是Python中最有名的ORM工具. 关于ORM: 全称Object Relational Mapping(对象关系映射). 特点是操纵Python对象而不是SQL查询,也就是在代码层面考虑的是对象,而不是SQL,体现的是一种程序化思维,这样使得Python程序更加简洁易读. 具体的实现方式是将数据库表转换为Python类,其中数据列

Python—sqlalchemy

SQLAlchemy SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作. #Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作: ''' MySQL-Python mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql mysql+pymysq

python sqlalchemy中commit提交错误--项非空不能插入空数据

非常白痴的问题,插入数据库提交失败,一直走IntegrityError错误,没打印错误信息,以为插不进去,弄了好久,最后打印了错误信息 (sqlite3.IntegrityError) samples.file_type may not be NULL [SQL: u'INSERT INTO samples (file_size, file_type, md5, crc32, sha1, sha256, sha512, ssdeep) VALUES (?, ?, ?, ?, ?, ?, ?, ?

Python - SQLAlchemy之连表操作

ORM的两种创建方式 数据库优先:指的是先创建数据库,包括表和字段的建立,然后根据数据库生成ORM的代码,它是先创建数据库,再创建相关程序代码 代码优先:就是先写代码,然后根据代码去生成数据库结构. 代码优先创建数据库的本质:拿到类-->转换成table对象, 然后根据table对象生成sql语句--> 生成数据库表结构 另外两个知识点: 改变数据输出的方式:可以在表的类中定义一个特殊成员:__repr__,return一个自定义的由字符串拼接的数据连接方式. 数据库中表关系之间除了MySQL