Python SQLAlchemy ORM

Python SQLAlchemy(SQLAlchemy ORM)

這篇 SQLAlchemy 教學介紹 ORM(Object Relational Mapping):把資料表對應成 Python 類別、把資料列對應成物件——用第 27 篇學的 class 操作資料庫,不用手寫 SQL 字串。SQLAlchemy 是 Python 最主流的 ORM,本文使用 2.0 語法。

比較直接寫 SQLORM
寫法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 跟網路世界要資料。

延伸閱讀