SQLAlchemy 2.0 查詢使用指南

SQLAlchemy 2.0 查詢使用指南

1. 環境設置

首先,需要安裝 SQLAlchemy 2.0 版本。假設你使用的是 SQLite 數據庫,可以通過以下命令安裝 SQLAlchemy:

pip install sqlalchemy

接著,我們創建數據庫連接并初始化會話:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker# 創建數據庫引擎
engine = create_engine('sqlite:///example.db', echo=True)# 創建會話
Session = sessionmaker(bind=engine)
session = Session()

2. 定義數據模型

SQLAlchemy 使用 ORM (對象關系映射) 使得 Python 對象和數據庫表之間實現映射。以下是定義 User? 和 Address? 表的模型示例:

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationshipBase = declarative_base()class User(Base):__tablename__ = 'users'id = Column(Integer, primary_key=True)name = Column(String)age = Column(Integer)# 一對多關系,用戶可以有多個地址addresses = relationship('Address', back_populates='user', lazy='select')class Address(Base):__tablename__ = 'addresses'id = Column(Integer, primary_key=True)user_id = Column(Integer, ForeignKey('users.id'))email = Column(String)# 反向關系user = relationship('User', back_populates='addresses')

在這個模型中,User? 表和 Address? 表通過 user_id? 建立了外鍵關聯,用戶可以有多個地址。

3. 基本查詢操作

SQLAlchemy 2.0 提供了一個更簡潔和一致的查詢接口。以下是一些常見的查詢操作。

3.1 查詢所有記錄

from sqlalchemy import selectstmt = select(User)
result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

SQL 原生查詢:

SELECT * FROM users;

3.2 查詢特定字段

查詢 name? 和 age? 字段:

stmt = select(User.name, User.age)
result = session.execute(stmt).all()for name, age in result:print(name, age)

SQL 原生查詢:

SELECT name, age FROM users;

3.3 查詢帶條件的記錄

查詢年齡大于 30 的用戶:

stmt = select(User).where(User.age > 30)
result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

SQL 原生查詢:

SELECT * FROM users WHERE age > 30;

3.4 排序查詢

根據年齡降序排列查詢用戶:

stmt = select(User).order_by(User.age.desc())
result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

SQL 原生查詢:

SELECT * FROM users ORDER BY age DESC;

3.5 限制查詢結果

限制返回的記錄數為 5:

stmt = select(User).limit(5)
result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

SQL 原生查詢:

SELECT * FROM users LIMIT 5;

4. 關聯查詢(Join)

4.1 懶查詢 (Lazy Loading)

懶查詢是 SQLAlchemy 默認的加載方式,只有在訪問關聯屬性時才會執行查詢。它通過延遲加載來避免不必要的查詢,但是可能導致 “N+1 查詢問題”。

# 查詢用戶,并訪問用戶的地址
user = session.query(User).first()  # 執行查詢,不查詢 addresses
print(user.name)  # 輸出用戶名稱addresses = user.addresses  # 當訪問 addresses 時,SQLAlchemy 會查詢 addresses 表
for address in addresses:print(address.email)

SQL 原生查詢:

SELECT * FROM users WHERE id = 1;
-- 查詢用戶的地址
SELECT * FROM addresses WHERE user_id = 1;

4.2 預加載(Eager Loading)

預加載是通過 JOIN 或子查詢一次性加載所有相關數據。常見的預加載方法有 joinedload?、subqueryload? 和 selectinload?。

4.2.1 joinedload?

?joinedload? 會通過 JOIN 一次性加載所有相關數據,適用于關聯數據量少的情況。

from sqlalchemy.orm import joinedloadstmt = select(User).options(joinedload(User.addresses))
result = session.execute(stmt).scalars().all()for user in result:print(user.name)for address in user.addresses:print(address.email)

SQL 原生查詢:

SELECT * FROM users
JOIN addresses ON users.id = addresses.user_id;
4.2.2 subqueryload?

?subqueryload? 使用子查詢來加載關聯數據,適用于關聯數據較多的情況。

from sqlalchemy.orm import subqueryloadstmt = select(User).options(subqueryload(User.addresses))
result = session.execute(stmt).scalars().all()for user in result:print(user.name)for address in user.addresses:print(address.email)

SQL 原生查詢:

SELECT * FROM users;
-- 查詢 addresses 表的所有數據
SELECT * FROM addresses WHERE user_id IN (1, 2, 3, ...);
4.2.3 selectinload?

?selectinload? 適用于多對一和一對多的關系,能夠通過一次查詢批量加載所有關聯數據。

from sqlalchemy.orm import selectinloadstmt = select(User).options(selectinload(User.addresses))
result = session.execute(stmt).scalars().all()for user in result:print(user.name)for address in user.addresses:print(address.email)

SQL 原生查詢:

SELECT * FROM users;
-- 查詢 addresses 表
SELECT * FROM addresses WHERE user_id IN (1, 2, 3, ...);

4.3 延遲加載與預加載的比較

特性懶查詢 (Lazy Loading)預加載 (Eager Loading)
數據加載方式延遲加載,直到訪問關聯屬性時才查詢一次性加載所有關聯數據
查詢次數可能多次查詢(N+1 查詢問題)一次性查詢,通常只發出少量查詢
性能對于小數據量高效對于復雜查詢避免 N+1 問題,適用于大量關聯數據
常用方法?joinedload?、subqueryload?、selectinload?

5. 高級查詢

5.1 聚合查詢

SQLAlchemy 支持聚合函數,如 count?、sum?、avg? 等。以下是計算用戶數量的例子:

from sqlalchemy import funcstmt = select(func.count(User.id))
result = session.execute(stmt).scalar()
print(f"User Count: {result}")

SQL 原生查詢:

SELECT COUNT(id) FROM users;

5.2 分組查詢

通過 group_by? 方法進行分組查詢:

stmt = select(User.age, func.count(User.id)).group_by(User.age)
result = session.execute(stmt).all()for age, count in result:print(f"Age: {age}, Count: {count}")

SQL 原生查詢:

SELECT age, COUNT(id) FROM users GROUP BY age;

5.3 子查詢

通過子查詢來執行更復雜的查詢:

subquery = select(func.max(User.age)).scalar_subquery()
stmt = select(User).where(User.age == subquery)
result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

SQL 原生查詢:

SELECT * FROM users WHERE age = (SELECT MAX(age) FROM users);

6. 事務管理

SQLAlchemy 2.0 自動管理事務,但你也可以顯式地管理事務。例如:

from sqlalchemy.exc import SQLAlchemyErrortry:new_user = User(name="David", age=28)session.add(new_user)session.commit()  # 提交事務
except SQLAlchemyError:session.rollback()  # 回滾事務print("事務失敗,已回滾")

7. 總結

SQLAlchemy 2.0 提供了強大的 ORM 功能和靈活的查詢接口。合理選擇懶查詢和預加載策略可以有效避免性能問題,特別是對于關系復雜的數據模型,預加載能幫助避免 N+1 查詢問題。通過使用 select()?、joinedload?、subqueryload? 等方法,我們可以優化查詢性能,提高數據操作的效率。

當然,以下是更詳細的 SQLAlchemy 2.0 查詢使用指南,包括懶查詢(Lazy Loading)、預加載(Eager Loading)以及異步 session? 使用示例。我們將通過詳細的案例來解釋這些概念,幫助團隊成員全面理解 SQLAlchemy 2.0 的使用方式。


SQLAlchemy 2.0 查詢使用指南

1. 環境設置

首先,確保安裝了 SQLAlchemy 2.0:

pip install sqlalchemy

對于異步支持,確保你安裝了 asyncpg?(適用于 PostgreSQL)或 aiomysql?(適用于 MySQL)等異步數據庫驅動。

pip install sqlalchemy[asyncio] asyncpg

1.1 創建數據庫引擎和會話

數據庫連接使用 create_engine()? 來創建數據庫引擎,會話使用 sessionmaker()? 來創建。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker# 創建數據庫引擎
engine = create_engine('sqlite+aiosqlite:///example.db', echo=True, future=True)# 創建異步會話
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine# 異步引擎
engine = create_async_engine('sqlite+aiosqlite:///example.db', echo=True, future=True)# 異步會話
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

2. 定義數據模型

SQLAlchemy ORM 通過 declarative_base()? 定義數據庫模型。這里我們定義 User? 和 Address? 模型。

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationshipBase = declarative_base()class User(Base):__tablename__ = 'users'id = Column(Integer, primary_key=True)name = Column(String)age = Column(Integer)# 一對多關系addresses = relationship('Address', back_populates='user', lazy='select')class Address(Base):__tablename__ = 'addresses'id = Column(Integer, primary_key=True)user_id = Column(Integer, ForeignKey('users.id'))email = Column(String)user = relationship('User', back_populates='addresses')

2.1 解釋模型

在這個模型中,User? 表有一個一對多關系與 Address? 表關聯,User? 表的 addresses? 屬性代表用戶的多個地址,而 Address? 表的 user? 屬性反向關聯用戶。

3. 基本查詢操作

SQLAlchemy 2.0 提供了更加直觀的查詢接口。以下是一些常見的查詢操作。

3.1 查詢所有記錄

查詢 User? 表中的所有用戶數據:

from sqlalchemy import select# 創建查詢語句
stmt = select(User)# 執行查詢
with session.begin():result = session.execute(stmt).scalars().all()# 輸出結果
for user in result:print(user.name, user.age)

原生 SQL 查詢:

SELECT * FROM users;

3.2 查詢特定字段

查詢 name? 和 age? 字段的用戶數據:

stmt = select(User.name, User.age)with session.begin():result = session.execute(stmt).all()for name, age in result:print(name, age)

原生 SQL 查詢:

SELECT name, age FROM users;

3.3 查詢帶條件的記錄

查詢年齡大于 30 的用戶:

stmt = select(User).where(User.age > 30)with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

原生 SQL 查詢:

SELECT * FROM users WHERE age > 30;

3.4 排序查詢

按年齡降序排列查詢:

stmt = select(User).order_by(User.age.desc())with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

原生 SQL 查詢:

SELECT * FROM users ORDER BY age DESC;

3.5 限制查詢結果

限制返回前 5 條記錄:

stmt = select(User).limit(5)with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

原生 SQL 查詢:

SELECT * FROM users LIMIT 5;

4. 關聯查詢(Join)

SQLAlchemy 提供了強大的關聯查詢功能。我們可以使用 joinedload?、subqueryload? 等方法來優化查詢。

4.1 懶查詢 (Lazy Loading)

懶查詢是 SQLAlchemy 默認的加載方式。只有當你訪問某個關聯屬性時,SQLAlchemy 會延遲加載數據。

user = session.query(User).first()  # 執行查詢,不查詢 addresses
print(user.name)  # 輸出用戶名稱
addresses = user.addresses  # 此時會查詢 addresses 表
for address in addresses:print(address.email)

原生 SQL 查詢:

SELECT * FROM users WHERE id = 1;
-- 查詢地址
SELECT * FROM addresses WHERE user_id = 1;

4.2 預加載(Eager Loading)

為了避免 N+1 查詢問題,可以使用預加載。以下是幾種常用的預加載方式。

4.2.1 joinedload?

?joinedload? 使用 SQL JOIN 一次性加載所有關聯數據,適用于數據量較小的場景。

from sqlalchemy.orm import joinedloadstmt = select(User).options(joinedload(User.addresses))with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name)for address in user.addresses:print(address.email)

原生 SQL 查詢:

SELECT * FROM users
JOIN addresses ON users.id = addresses.user_id;
4.2.2 subqueryload?

?subqueryload? 使用子查詢加載關聯數據,適用于關聯數據較多的情況。

from sqlalchemy.orm import subqueryloadstmt = select(User).options(subqueryload(User.addresses))with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name)for address in user.addresses:print(address.email)

原生 SQL 查詢:

SELECT * FROM users;
-- 查詢 addresses 表的所有數據
SELECT * FROM addresses WHERE user_id IN (1, 2, 3, ...);
4.2.3 selectinload?

?selectinload? 通過批量查詢一次性加載關聯數據,適用于多對一和一對多的關系。

from sqlalchemy.orm import selectinloadstmt = select(User).options(selectinload(User.addresses))with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name)for address in user.addresses:print(address.email)

原生 SQL 查詢:

SELECT * FROM users;
-- 查詢 addresses 表
SELECT * FROM addresses WHERE user_id IN (1, 2, 3, ...);

4.3 延遲加載與預加載的比較

特性懶查詢 (Lazy Loading)預加載 (Eager Loading)
數據加載方式延遲加載,直到訪問關聯屬性時才查詢一次性加載所有關聯數據
查詢次數可能多次查詢(N+1 查詢問題)一次性查詢,通常只發出少量查詢
性能對于小數據量高效對于復雜查詢避免 N+1 問題,適用于大量關聯數據
常用方法?joinedload?、subqueryload?、selectinload?

5. 高級查詢

5.1 聚合查詢

SQLAlchemy 支持聚合函數,如 count?、sum?、avg? 等。以下是計算用戶數量的例子:

from sqlalchemy import funcstmt = select(func.count(User.id))with session.begin():result = session.execute(stmt).scalar()print(f"User Count: {result}")

SQL 原生查詢:

SELECT COUNT(id) FROM users;

5.2 分組查詢

通過 group_by? 方法進行分組查詢:

stmt = select(User.age, func.count(User.id)).group_by(User.age)with session.begin():result = session.execute(stmt).all()for age, count in result:print(f"Age: {age}, Count: {count}")

SQL 原生查詢:

SELECT age, COUNT(id) FROM users GROUP BY age;

5.3 子查詢

通過子查詢來執行更復雜的查詢:

subquery = select(func.max(User.age)).scalar_subquery()stmt = select(User).where(User.age == subquery)with session.begin():result = session.execute(stmt).scalars().all()for user in result:print(user.name, user.age)

SQL 原生查詢:

SELECT * FROM users WHERE age = (SELECT MAX(age) FROM users);

6. 異步查詢使用示例

SQLAlchemy 支持異步查詢,適用于需要處理高并發操作的場景。以下是使用異步 session? 進行查詢的示例。

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.future import select# 創建異步引擎和會話
engine = create_async_engine('sqlite+aiosqlite:///example.db', echo=True, future=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)async def async_query():async with async_session() as session:stmt = select(User)result = await session.execute(stmt)users = result.scalars().all()for user in users:print(user.name)# 執行異步查詢
import asyncio
asyncio.run(async_query())

在異步查詢中,我們使用 await? 來執行查詢,確保數據庫操作不會阻塞主線程。

7. 總結

SQLAlchemy 2.0 提供了靈活且高效的查詢功能,支持懶查詢、預加載和異步操作。通過合理使用懶查詢和預加載,可以有效地避免 N+1 查詢問題,提高應用性能。在異步操作方面,SQLAlchemy 的異步會話使得我們可以在高并發環境下高效地進行數據庫查詢。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82301.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82301.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82301.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows 使用 WSL 安裝 Ubuntu

一,前言 Windows 上輕松跑 Linux 又不想用笨重的VMware 和VirtualBox ,怎么辦? 開源項目 Windows Subsystem for Linux (WSL)。它解決了許多開發者在 Windows 和 Linux 間切換的痛點,實現在 Windows 上無縫跑 Linux 工具和命令。…

[Excel VBA]如何製作買三送一優惠條件的POS結帳介面?

Excel I VBA I 買三送一優惠條件的POS結帳機 因應商品特賣活動,結帳介面需整合特定優惠條件,如買三送一,買五送二等等優惠條件。本文封面影片以買三送一為範例,並搭配VBA和對應按鈕,而實現銷售訂單紀錄和即時更新庫存等…

3d世界坐標系轉屏幕坐標系

世界坐標 ——> NDC標準設備坐標 ——> 屏幕坐標 標準設備NDC坐標系 屏幕坐標系 .project方法將 將向量(坐標)從世界空間投影到相機的標準化設備坐標 (NDC) 空間。 手動實現HTML元素定位到模型位置,實現模型標簽效果(和css2Render原理同理&#…

Idea出現 100% classes 等

總是誤點出來,每次又忘了怎么消除,在這里記錄一下。 出現這樣: 操作idea界面的:點擊View->Tool Windows ->Coverage,然后關掉

從零開始學習QT——第一步

一、Qt 1.1、Qt是什么 Qt是一個跨平臺的C圖形用戶界面應用程序框架。它為應用程序開發者提供建立圖形界面所需的所有功能。它是完全面向對象的,很容易擴展,并且允許真正的組件編程。 1.2、Qt的發展歷程 1991年 Qt最早由芬蘭奇趣科技開發 1996年 進入商業…

MySQL 8.0 OCP 1Z0-908 171-180題

Q171.Examine this MySQL client command to connect to a remote database: mysql-h remote-example.org-u root–protocolTCP–ssl-mode Which two–ss1-mode values will ensure that an X.509-compliant certificate will be used to establish the SSL/TLS connection to …

【機器學習】 關于外插修正隨機梯度方法的數值實驗

1. 隨機梯度下降(SGD) 迭代格式: x k 1 x k ? η k ? f i ( x k ) x_{k1} x_k - \eta_k \nabla f_i(x_k) xk1?xk??ηk??fi?(xk?) 其中, η k \eta_k ηk? 為步長(可能遞減), ? f…

每日c/c++題 備戰藍橋杯(洛谷P3382 三分法求極值詳解)

洛谷P3382 三分法求極值詳解 題目描述 P3382 三分法 要求在給定區間內尋找一個多項式函數的最大值點。題目保證函數在區間內先嚴格遞增后嚴格遞減(單峰函數),適合使用三分法求解。 算法原理 三分法核心思想 對于單峰函數,在區…

[Windows] 一鍵實現重復工作自動化zTasker

zTasker,是一款定時|熱鍵|純粹的自動化任務神器。它支持超過100種任務類型,包括提醒、關機重啟、報時、擋屏休息、文件備份、音量調節、靜音等。用戶可以通過定時、CPU占用、文件夾監控、網速、快捷鍵等多種條件觸發任務。 簡單點…

Docker核心筆記

一、概述 1、架構 Docker容器基于鏡像運行,容器共享宿主機的內核,不會加載額外內核,通過Namespaces(環境隔離)和Cgroups(資源控制)實現隔離,Cgroups會限容器使用資源并控制優先級和統計數據。隔離后的容器僅包含應用所需的用戶態依賴 2、安裝 安裝先卸載再安裝,使用的yum…

2025年電工杯數學建模B題【垃圾運輸】原創論文分享

大家好呀,從發布賽題一直到現在,總算完成了2025年電工杯數學建模B題【垃圾運輸】完整的成品論文。 給大家看一下目錄吧: 目錄 摘 要: 一、問題重述 二.問題分析 2.1問題一 2.2問題二 2.3問題三 三、模型假設 …

[爬蟲知識] IP代理

相關實戰案例:[爬蟲實戰] 代理爬取:小白也能看懂怎么用代理 相關爬蟲專欄:JS逆向爬蟲實戰 爬蟲知識點合集 爬蟲實戰案例 引言:爬蟲與IP封鎖的攻防戰 對網絡爬蟲而言,遇到的一個較棘手的問題就是封IP:請…

計算機視覺---YOLOv1

YOLOv1深度解析:單階段目標檢測的開山之作 一、YOLOv1概述 提出背景: 2016年由Joseph Redmon等人提出,全稱"You Only Look Once",首次將目標檢測視為回歸問題,開創單階段(One-Stage&#xff09…

前端學習筆記element-Plus

【element-plus菜單】參數說明: active-text-color"#ffd04b"——激活顏色 background-color"#232323"——背景顏色(29,160,176) :default-active"$route.path"——配置默認高亮的菜單項 text-color"#f…

【Django DRF】一篇文章總結Django DRF框架

第一章 DRF框架基礎 1.1 DRF簡介 1.1.1 DRF定義與作用 1. 定義 DRF 即 Django REST framework,它是一個建立在 Django 基礎之上的強大且靈活的工具包,用于構建 Web API(應用程序編程接口)😎。簡單來說,…

如何解決 Python 項目安裝依賴報錯:ERROR: Failed to build installable wheels for some pyproject.toml based project

如何解決 Python 項目安裝依賴報錯:ERROR: Failed to build installable wheels for some pyproject.toml based projects 在使用 pip 安裝 Python 項目的依賴時,遇到類似如下的報錯信息: ERROR: Failed to build installable wheels for s…

使用f5-tts訓練自己的模型筆記

摘要 服務器都有了,這不得練練丹,有點說不過去啊。所以嘗試了從頭開始訓練一個模型,結果由于推理頁面好像有bug,不知道是不是失敗了,然后又嘗試微調一下模型。本篇文章主要記錄了三流調包俠嘗試煉丹過程中學習到的一些…

安全可控的AI底座:燈塔大模型應用開發平臺全面實現國產信創兼容適配認證

國產信創產品兼容適配認證是為了支持和推動國產信息技術產品和服務的發展而設立的一種質量標準和管理體系。適配認證旨在確保相關產品在安全性、可靠性、兼容性等方面達到一定的標準,以滿足政府和關鍵行業對信息安全和自主可控的需求。 北京中煙創新科技有限公司&a…

初識Vue【1】

1.什么是Vue: Vue (讀音 /vju?/,類似于 **view**) 是一套用于構建用戶界面的**漸進式框架**。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注視圖層,不僅易于上手,還便于與第三方庫或…

Jest入門

快速入門 Jest中文文檔 | Jest中文網 1.下載:npm install --save-dev jest 2.創建 sum.js 文件: function sum(a, b) { return a b; } module.exports sum; 3.創建sum.test.js 的文件 const sum require(./sum); test(adds 1 2 to equal 3,…