Python SQLAlchemy(SQLAlchemy ORM)
這篇 SQLAlchemy 教學介紹 ORM(Object Relational Mapping):把資料表對應成 Python 類別、把資料列對應成物件——用第 27 篇學的 class 操作資料庫,不用手寫 SQL 字串。SQLAlchemy 是 Python 最主流的 ORM,本文使用 2.0 語法。
| 比較 | 直接寫 SQL | ORM |
|---|---|---|
| 寫法 | SQL 字串 | Python 類別與方法 |
| 換資料庫 | 語法差異要自己處理 | 幾乎不用改程式 |
| 複雜查詢 | 彈性最大 | 過於複雜時反而繞 |
| 適合 | 報表、效能調校 | 一般 CRUD、中大型專案 |
安裝:uv add sqlalchemy。
定義模型(資料表 ↔ 類別)
from sqlalchemy import create_engine, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Student(Base):
__tablename__ = "students"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
score: Mapped[int]
def __repr__(self):
return f"Student(name={self.name!r}, score={self.score})"
# 連線(示範用 SQLite,換 MySQL 只要改這行連線字串)
engine = create_engine("sqlite:///school.db")
Base.metadata.create_all(engine) # 依模型自動建表
print("資料表就緒")
執行輸出:
資料表就緒
一個類別=一張表、一個屬性=一個欄位(型別用第 31 篇的 Type Hints 標注)。連 MySQL 時連線字串改成 "mysql+pymysql://帳號:密碼@localhost/school" 即可,程式其他部分不用動——這就是 ORM 的可攜性。
新增資料:Session
with Session(engine) as session:
session.add(Student(name="小明", score=85))
session.add_all([
Student(name="小華", score=92),
Student(name="小美", score=78),
])
session.commit()
print("新增完成")
執行輸出:
新增完成
Session 是 ORM 的交易窗口:add 排入、commit 寫入,模式跟 sqlite3 的 commit 一致。
查詢資料:select()
from sqlalchemy import select
with Session(engine) as session:
stmt = select(Student).where(Student.score >= 80).order_by(Student.score.desc())
for s in session.scalars(stmt):
print(s)
執行輸出:
Student(name='小華', score=92)
Student(name='小明', score=85)
對照 SQL:select(Student) ≈ SELECT、.where() ≈ WHERE、.order_by() ≈ ORDER BY——概念完全相通,只是換成方法鏈。
更新與刪除
ORM 風格是「取出物件、改屬性、commit」:
with Session(engine) as session:
s = session.scalars(select(Student).where(Student.name == "小美")).first()
if s:
s.score = 90 # 直接改屬性
session.commit()
print("更新完成:", s)
執行輸出:
更新完成: Student(name='小美', score=90)
刪除則是 session.delete(s) 後 commit。
常見錯誤
1. 改了物件卻沒存進資料庫
忘記 session.commit()。Session 內的變更只存在記憶體,commit 才落地。
2. no such table
忘了 Base.metadata.create_all(engine),或 engine 連到不同的資料庫檔案。
3. 混用 1.x 與 2.0 語法
網路上大量舊教學用 session.query(Student)(1.x 風格)。能動,但新專案統一用 select() + session.scalars() 的 2.0 寫法,跟官方文件與型別檢查的相容性最好。
總結
ORM 把表變類別、列變物件:DeclarativeBase 定義模型、create_all 建表、Session + add/commit 寫入、select().where() 查詢;換資料庫只改連線字串。SQL 基礎(本站 SQL 系列)依然重要——ORM 生成的就是 SQL,看得懂才除得了錯。下一篇離開資料庫,學會用 requests 跟網路世界要資料。
延伸閱讀
- Python 教學(系列目錄)
- Python sqlite3 資料庫操作
- Python 類別與物件
- Python Type Hints 型別提示
- SQL 教學(本站 SQL 系列)
- Python requests 網路請求(下一篇)