Python中SQLAlchemy庫(kù)的使用方法分析
1. 基本知識(shí)
一、ORM (對(duì)象關(guān)系映射):
- SQLAlchemy 是Python SQL工具包和對(duì)象關(guān)系映射器(ORM),允許Python開(kāi)發(fā)者在應(yīng)用程序中使用SQL來(lái)交互,而無(wú)需處理數(shù)據(jù)庫(kù)的具體細(xì)節(jié)
- 提供一個(gè)高層的抽象層,允許開(kāi)發(fā)者通過(guò)Python類(lèi)和對(duì)象來(lái)表示數(shù)據(jù)庫(kù)中的表和行,從而使得數(shù)據(jù)庫(kù)操作更加方便和靈活
二、核心(Core):
SQLAlchemy 的核心部分提供了一組工具來(lái)執(zhí)行SQL操作,包括創(chuàng)建和執(zhí)行SQL語(yǔ)句
、連接池管理
、事務(wù)管理
等。開(kāi)發(fā)者可以使用核心部分來(lái)執(zhí)行一些高級(jí)的數(shù)據(jù)庫(kù)操作,如自定義SQL語(yǔ)句
、連接到數(shù)據(jù)庫(kù)
等。
三、優(yōu)點(diǎn):
靈活性
:
多種不同的方式來(lái)與數(shù)據(jù)庫(kù)交互,包括使用核心部分執(zhí)行原始SQL語(yǔ)句、使用ORM進(jìn)行對(duì)象關(guān)系映射、以及使用表達(dá)式語(yǔ)言構(gòu)建SQL查詢等
功能豐富
:
許多功能豐富的工具和API,滿足各種不同的數(shù)據(jù)庫(kù)操作需求
ORM支持
:
SQLAlchemy 的ORM工具允許開(kāi)發(fā)者使用Python類(lèi)來(lái)代表數(shù)據(jù)庫(kù)中的表和行,從而使得數(shù)據(jù)庫(kù)操作更加Pythonic和易于理解
ORM工具提供了一種高級(jí)的抽象,隱藏了底層數(shù)據(jù)庫(kù)操作的細(xì)節(jié),使得開(kāi)發(fā)者可以更專(zhuān)注于業(yè)務(wù)邏輯的實(shí)現(xiàn)
跨數(shù)據(jù)庫(kù)支持
:
支持多種不同的數(shù)據(jù)庫(kù)后端,包括MySQL、PostgreSQL、SQLite等
活躍的社區(qū)
:
SQLAlchemy 有一個(gè)活躍的社區(qū),提供了大量的文檔、教程和示例代碼,使得開(kāi)發(fā)者可以更容易地學(xué)習(xí)和使用這個(gè)工具包
四、缺點(diǎn):性能開(kāi)銷(xiāo)
盡管SQLAlchemy提供了許多便利的功能,但有時(shí)候這些功能可能會(huì)帶來(lái)一定的性能開(kāi)銷(xiāo)。特別是在處理大量數(shù)據(jù)或需要高性能的場(chǎng)景下,可能需要仔細(xì)優(yōu)化代碼以減少性能損失
五、與其他工具比較:
與其他ORM工具的比較:
Django ORM | Peewee | SQLObject |
---|---|---|
與Django ORM相比,SQLAlchemy提供了更多的靈活性和功能,尤其是在處理復(fù)雜數(shù)據(jù)庫(kù)操作和跨數(shù)據(jù)庫(kù)支持方面 但Django ORM更容易上手,并且與Django框架無(wú)縫集成,適合快速開(kāi)發(fā)和小型項(xiàng)目 | Peewee 是另一個(gè)輕量級(jí)的Python ORM工具,相比于SQLAlchemy,它的學(xué)習(xí)曲線更為平緩,適合于簡(jiǎn)單的數(shù)據(jù)庫(kù)操作和小型項(xiàng)目 但Peewee的功能相對(duì)較少,不如SQLAlchemy靈活 | SQLObject 是另一個(gè)Python ORM庫(kù),它的設(shè)計(jì)更加接近于Active Record模式,與SQLAlchemy的Data Mapper模式有所不同 但SQLObject的學(xué)習(xí)曲線較陡,且功能相對(duì)較少,通常適用于簡(jiǎn)單的數(shù)據(jù)庫(kù)操作 |
2. 基本API
- 安裝庫(kù):
pip install SQLAlchemy
- 驗(yàn)證是否安裝成功:
python -c "import sqlalchemy; print(sqlalchemy.__version__)"
或者pip show sqlalchemy
為了讓大家更快上手,先學(xué)習(xí)下下面這個(gè)實(shí)戰(zhàn)項(xiàng)目:
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base # 創(chuàng)建引擎 engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin') # 創(chuàng)建Session Session = sessionmaker(bind=engine) session = Session() # 定義映射類(lèi) Base = declarative_base() class User(Base): __tablename__ = 'manong' id = Column(Integer, primary_key=True) name = Column(String(255)) # 在這里指定了 name 列的長(zhǎng)度為 255 age = Column(Integer) # 創(chuàng)建表 Base.metadata.create_all(engine) # 插入數(shù)據(jù) new_user = User(name='yanjiuseng', age=25) session.add(new_user) session.commit() # 查詢數(shù)據(jù) query = session.query(User).filter(User.age > 18) result = query.all() for user in result: print(user.name, user.age)
最終截圖如下:
通過(guò)看完整個(gè)代碼邏輯,帶著一些小疑問(wèn),深入探討下這些API的使用方式
2.1 create_engine(創(chuàng)建引擎)
create_engine
函數(shù)用于創(chuàng)建一個(gè)與數(shù)據(jù)庫(kù)的連接引擎,該引擎可以執(zhí)行SQL操作
from sqlalchemy import create_engine engine = create_engine('mysql+pymysql://username:password@host:port/database')
針對(duì)里頭的參數(shù)解釋如下:
mysql
:指定數(shù)據(jù)庫(kù)類(lèi)型,這里是 MySQL 數(shù)據(jù)庫(kù)username
:數(shù)據(jù)庫(kù)用戶名password
:數(shù)據(jù)庫(kù)密碼host
:數(shù)據(jù)庫(kù)主機(jī)名或 IP 地址port
:數(shù)據(jù)庫(kù)端口號(hào),默認(rèn)是 MySQL 的端口號(hào) 3306database
:要連接的數(shù)據(jù)庫(kù)名稱(chēng)
MySQL 數(shù)據(jù)庫(kù)用戶名是 user1,密碼是 pass123,主機(jī)名是 localhost,端口號(hào)是 3306,要連接的數(shù)據(jù)庫(kù)名稱(chēng)是 my_database,那么連接字符串就應(yīng)該是:
'mysql://user1:pass123@localhost:3306/my_database'
對(duì)于數(shù)據(jù)庫(kù)類(lèi)型常用的:mysql+pymysql
,主要區(qū)別在于其使用的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序不同。
mysql+pymysql
:(更簡(jiǎn)單地安裝和使用,可以選擇使用 pymysql)
指定使用 PyMySQL 作為連接 MySQL 數(shù)據(jù)庫(kù)的驅(qū)動(dòng)程序,PyMySQL 是一個(gè)純 Python 實(shí)現(xiàn)的 MySQL 客戶端庫(kù),兼容 Python 數(shù)據(jù)庫(kù) API 規(guī)范 2.0,可以在 Python 中直接使用mysql
:(對(duì)性能要求比較高,可以選擇使用 mysql 并配合 MySQLdb 或者 mysqlclient)
沒(méi)有指定具體的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序,使用默認(rèn)的 MySQL 客戶端庫(kù),一般情況下會(huì)使用 MySQLdb 或者 mysqlclient
再額外補(bǔ)充其他的URL格式:
# MySQL-Python: mysql+mysqldb://<user>:<password>@<host>:<port>/<dbname> # pymysql: mysql+pymysql://<username>:<password>@<host>:<port>/<dbname>?<options> # MySQL-Connector: mysql+mysqlconnector://<user>:<password>@<host>:<port>/<dbname> # cx_Oracle: oracle+cx_oracle://<user>:<password>@<host>:<port>/<dbname>?key=value&key=value...
2.2 sessionmaker(創(chuàng)建session)
用于創(chuàng)建一個(gè) Session 類(lèi),該類(lèi)用于執(zhí)行 ORM(對(duì)象關(guān)系映射)操作
主要作用是創(chuàng)建一個(gè)會(huì)話工廠,通過(guò)工廠可以創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話對(duì)象,用于在代碼中執(zhí)行數(shù)據(jù)庫(kù)操作
# 創(chuàng)建Session Session = sessionmaker(bind=engine) session = Session()
其中sessionmaker的參數(shù)如下:
bind
:要綁定到的數(shù)據(jù)庫(kù)引擎,通常是一個(gè) create_engine 函數(shù)返回的 Engine 對(duì)象class_
:可選參數(shù),指定要?jiǎng)?chuàng)建的會(huì)話類(lèi),默認(rèn)為 Session 類(lèi)autocommit
:是否自動(dòng)提交事務(wù),默認(rèn)為 Falseautoflush
:是否自動(dòng)刷新會(huì)話,默認(rèn)為 Trueexpire_on_commit
:在提交事務(wù)時(shí)是否自動(dòng)使對(duì)象過(guò)期,默認(rèn)為 Trueinfo
:一個(gè)字典,用于指定會(huì)話的其他配置信息
具體示例如下:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker # 創(chuàng)建引擎 engine = create_engine('sqlite:///example.db') # 創(chuàng)建會(huì)話工廠 Session = sessionmaker(bind=engine, autocommit=False, autoflush=True) # 創(chuàng)建會(huì)話對(duì)象 session = Session()
需要注意的點(diǎn)如下:
- 在使用會(huì)話對(duì)象執(zhí)行數(shù)據(jù)庫(kù)操作后,一般需要調(diào)用
commit
方法提交事務(wù),或者調(diào)用rollback
方法回滾事務(wù)。 - 在會(huì)話對(duì)象的作用域結(jié)束時(shí),通常需要調(diào)用
close
方法關(guān)閉會(huì)話,釋放數(shù)據(jù)庫(kù)連接資源。
2.3 declarative_base(定義映射類(lèi))
使用 ORM 進(jìn)行數(shù)據(jù)庫(kù)操作的核心部分之一,涉及到將數(shù)據(jù)庫(kù)中的表映射到 Python 中的類(lèi),以及定義類(lèi)屬性來(lái)表示表的列
一、映射類(lèi)的定義:
通過(guò)創(chuàng)建Python 類(lèi)來(lái)表示數(shù)據(jù)庫(kù)中的表
該類(lèi)通常繼承自 SQLAlchemy 的 Base 類(lèi),而 Base 類(lèi)是使用 declarative_base()
函數(shù)創(chuàng)建的
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()
二、表的映射:
在映射類(lèi)中定義 __tablename__
屬性,指定該類(lèi)所映射的數(shù)據(jù)庫(kù)表的名稱(chēng)
class User(Base): __tablename__ = 'users'
三、列的映射:
在映射類(lèi)中定義類(lèi)屬性,來(lái)表示表中的列
每個(gè)類(lèi)屬性通常都會(huì)被定義為 Column
對(duì)象,并指定其數(shù)據(jù)類(lèi)型以及其他屬性
from sqlalchemy import Column, Integer, String class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(255)) age = Column(Integer)
對(duì)應(yīng)的屬性如下:
屬性的含義:
Column
:表示一個(gè)數(shù)據(jù)庫(kù)表的列Integer
、String
等數(shù)據(jù)類(lèi)型:表示列的數(shù)據(jù)類(lèi)型primary_key=True
:指定該列為主鍵
其他參數(shù):例如長(zhǎng)度、唯一性等,用于進(jìn)一步定義列的屬性
2.4 SQL與ORM差異
一、基于 SQL 的查詢:
特點(diǎn):
原始的 SQL 查詢語(yǔ)句,手動(dòng)編寫(xiě) SQL 語(yǔ)句來(lái)執(zhí)行數(shù)據(jù)庫(kù)操作。于執(zhí)行復(fù)雜的查詢、跨表查詢或性能要求較高的場(chǎng)景
示例代碼:
from sqlalchemy import create_engine, text # 創(chuàng)建引擎 engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin') # 執(zhí)行 SQL 查詢 with engine.connect() as connection: result = connection.execute(text("SELECT * FROM manong WHERE age > :age"), {'age': 18}) for row in result: print(row)
截圖如下:
二、基于ORM查詢:
- 操作對(duì)象來(lái)執(zhí)行數(shù)據(jù)庫(kù)操作,而不需要編寫(xiě)原始的 SQL 語(yǔ)句
- 提供了更加 Pythonic 和面向?qū)ο蟮慕涌冢沟么a更加清晰和易于維護(hù)
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base # 創(chuàng)建引擎 engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin') # 創(chuàng)建Session Session = sessionmaker(bind=engine) session = Session() # 定義映射類(lèi) Base = declarative_base() class User(Base): __tablename__ = 'manong' id = Column(Integer, primary_key=True) name = Column(String(255)) # 在這里指定了 name 列的長(zhǎng)度為 255 age = Column(Integer) result = session.query(User).filter(User.age > 18).all() for user in result: print(user.name, user.age)
區(qū)別的方式在于:
- 實(shí)現(xiàn)方式:基于 SQL 的查詢直接使用原始的 SQL 語(yǔ)句,而基于 ORM 的查詢則是通過(guò) ORM 工具來(lái)執(zhí)行數(shù)據(jù)庫(kù)操作
- 編寫(xiě)方式:基于 SQL 的查詢需要開(kāi)發(fā)者手動(dòng)編寫(xiě) SQL 語(yǔ)句,而基于 ORM 的查詢則是通過(guò)操作對(duì)象來(lái)執(zhí)行數(shù)據(jù)庫(kù)操作,不需要編寫(xiě)原始的 SQL 語(yǔ)句
- 靈活性:基于 SQL 的查詢更加靈活,可以執(zhí)行復(fù)雜的原始 SQL 查詢,而基于 ORM 的查詢提供了更加 Pythonic 和面向?qū)ο蟮慕涌?,使得代碼更加清晰和易于維護(hù)
3. ORM CRUD
對(duì)于基本的SQL查詢,需要編寫(xiě)SQL語(yǔ)句,此處偏向?qū)崙?zhàn)類(lèi),所以詳細(xì)補(bǔ)充ORM CRUD的的基本知識(shí)
前半部分代碼如下:
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base # 創(chuàng)建引擎 engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin') # 創(chuàng)建Session Session = sessionmaker(bind=engine) session = Session() # 定義映射類(lèi) Base = declarative_base() class User(Base): __tablename__ = 'manong' id = Column(Integer, primary_key=True) name = Column(String(255)) # 在這里指定了 name 列的長(zhǎng)度為 255 age = Column(Integer) # 創(chuàng)建表 Base.metadata.create_all(engine)
3.1 增加(C)
- 添加單個(gè)對(duì)象:將新對(duì)象添加到數(shù)據(jù)庫(kù)中
user = User(name='AA', age=30) session.add(user) session.commit()
- 添加多個(gè)對(duì)象:將多個(gè)新對(duì)象批量添加到數(shù)據(jù)庫(kù)中
users = [User(name='BB', age=30), User(name='CC', age=25)] session.add_all(users) session.commit()
3.2 查找(R)
查詢所有對(duì)象:從數(shù)據(jù)庫(kù)中檢索所有對(duì)象
all_users = session.query(User).all()
根據(jù)條件查詢:根據(jù)指定條件過(guò)濾對(duì)象
# # 查詢數(shù)據(jù) result = session.query(User).filter(User.age > 18).all() for user in result: print(user.name, user.age)
查詢單個(gè)對(duì)象:從數(shù)據(jù)庫(kù)中檢索滿足條件的單個(gè)對(duì)象
user = session.query(User).filter_by(name='Alice').first()
3.3 更新(U)
更新單個(gè)對(duì)象:修改數(shù)據(jù)庫(kù)中的現(xiàn)有對(duì)象
user = session.query(User).filter_by(name='Alice').first() user.age = 35 session.commit()
批量更新:使用 update()
方法批量更新滿足條件的對(duì)象
session.query(User).filter(User.age < 30).update({'age': 30}) session.commit()
3.4 刪除(D)
刪除單個(gè)對(duì)象:從數(shù)據(jù)庫(kù)中刪除指定的對(duì)象
user = session.query(User).filter_by(name='Alice').first() session.delete(user) session.commit()
批量刪除:使用 delete()
方法批量刪除滿足條件的對(duì)象
session.query(User).filter(User.age > 30).delete() session.commit()
4. 彩蛋
4.1 建表Bug
建表的過(guò)程中如果語(yǔ)句如下:
class Manong(Base): __tablename__ = 'manong' id = Column(Integer) name = Column(String)
報(bào)錯(cuò)信息如下: sqlalchemy.exc.CompileError: (in table 'manong', column 'name'): VARCHAR requires a length on dialect mysql
主要問(wèn)題如下:
在 MySQL 中,VARCHAR 類(lèi)型的列必須指定長(zhǎng)度,即字符的最大數(shù)量。
需要為表中的 VARCHAR 類(lèi)型的列指定長(zhǎng)度
將其代碼修改為:
from sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Manong(Base): __tablename__ = 'manong' id = Column(Integer, primary_key=True) name = Column(String(255)) # 在這里指定了 name 列的長(zhǎng)度為 255 # 繼續(xù)定義其他列和表結(jié)構(gòu)
如果不是建表,可以省略字段長(zhǎng)度
4.2 filter 和 filter_by
filter
方法使用類(lèi)名和屬性名來(lái)構(gòu)建查詢條件,比較通常使用==
,也可以使用其他比較操作符如>
,<
,>=
,<=
等filter_by
方法直接使用屬性名和相應(yīng)的值來(lái)構(gòu)建查詢條件,比較通常使用=
以下為簡(jiǎn)易Demo,方便理解:
# 使用 filter 方法 from sqlalchemy.orm import sessionmaker Session = sessionmaker(bind=engine) session = Session() # 查詢名字為 Alice 的記錄 alice_records = session.query(User).filter(User.name == 'Alice').all() # 查詢年齡大于等于 25 歲的記錄 older_users = session.query(User).filter(User.age >= 25).all() # 使用 filter_by 方法 # 查詢名字為 Alice 的記錄 alice_records = session.query(User).filter_by(name='Alice').all()
filter 的組合查詢: (這個(gè)在實(shí)戰(zhàn)中比較常用!?。。?/p>
通過(guò)連續(xù)調(diào)用來(lái)實(shí)現(xiàn)多個(gè)條件的組合查詢,或者使用AND 條件連接多個(gè)條件
# 使用 filter 連續(xù)添加條件查詢 # 查詢名字為 Alice 且年齡大于等于 25 歲的記錄 alice_older_records = session.query(User).filter(User.name == 'Alice').filter(User.age >= 25).all()
或者如下:
from sqlalchemy import and_ # 使用 and_ 函數(shù)連接兩個(gè)條件 alice_older_records = session.query(User).filter(and_(User.name == 'Alice', User.age >= 25)).all()
以上就是Python中SQLAlchemy庫(kù)的使用方法分析的詳細(xì)內(nèi)容,更多關(guān)于Python SQLAlchemy庫(kù)使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 分析解決Python中sqlalchemy數(shù)據(jù)庫(kù)連接池QueuePool異常
- 3個(gè)Python?SQLAlchemy數(shù)據(jù)庫(kù)操作功能詳解
- Python使用SQLAlchemy模塊實(shí)現(xiàn)操作數(shù)據(jù)庫(kù)
- Python?SQLAlchemy與數(shù)據(jù)庫(kù)交互操作完整指南
- Python使用sqlalchemy實(shí)現(xiàn)連接數(shù)據(jù)庫(kù)的幫助類(lèi)
- Python中使用sqlalchemy操作數(shù)據(jù)庫(kù)的問(wèn)題總結(jié)
- Python使用SQLAlchemy進(jìn)行復(fù)雜查詢的操作代碼
- Python如何使用sqlalchemy實(shí)現(xiàn)動(dòng)態(tài)sql
- python SQLAlchemy 數(shù)據(jù)庫(kù)連接池的實(shí)現(xiàn)
相關(guān)文章
詳解Python Matplotlib解決繪圖X軸值不按數(shù)組排序問(wèn)題
這篇文章主要介紹了詳解Python Matplotlib解決繪圖X軸值不按數(shù)組排序問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Python著名游戲?qū)崙?zhàn)之方塊連接 我的世界
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,學(xué)的扎不扎實(shí)要通過(guò)實(shí)戰(zhàn)才能看出來(lái),本篇文章手把手帶你模仿著名游戲——我的世界,大家可以在過(guò)程中查缺補(bǔ)漏,看看自己掌握程度怎么樣2021-10-10使用Python編寫(xiě)腳本來(lái)生成隨機(jī)密碼
在數(shù)字化時(shí)代,密碼已成為我們保護(hù)個(gè)人信息和數(shù)據(jù)安全的重要手段,然而,手動(dòng)創(chuàng)建復(fù)雜且難以猜測(cè)的密碼是一項(xiàng)既繁瑣又容易出錯(cuò)的任務(wù),本文將詳細(xì)介紹如何使用Python編寫(xiě)腳本來(lái)生成隨機(jī)密碼,并探討其背后的原理和技術(shù)細(xì)節(jié),需要的朋友可以參考下2024-10-10python3 selenium自動(dòng)化 frame表單嵌套的切換方法
今天小編就為大家分享一篇python3 selenium自動(dòng)化 frame表單嵌套的切換方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08python利用pandas將excel文件轉(zhuǎn)換為txt文件的方法
今天小編就為大家分享一篇python利用pandas將excel文件轉(zhuǎn)換為txt文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10keras 多任務(wù)多l(xiāng)oss實(shí)例
這篇文章主要介紹了keras 多任務(wù)多l(xiāng)oss實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06