Skip to content
 

SQLAlchemy 与数据库操作讲解

更新: 8/25/2026字数: 0 字 时长: 0 分钟

SQLAlchemy 是 Python 中最强大、最流行的 SQL 工具包,同时支持 ORM(对象关系映射)Core(核心表达式) 两种风格。现代项目推荐使用 SQLAlchemy 2.0 风格,API 更清晰、类型提示更好。

一、核心概念

概念说明
Engine数据库连接池的入口,负责管理连接
SessionORM 的工作单元,负责对象的增删改查
Model普通 Python 类,对应数据库表
Core更接近 SQL 的表达式语言,性能更高、更灵活
ORM用对象操作数据库,开发效率高

大多数 Web 项目(尤其 FastAPI)使用 ORM 风格即可。

二、安装

bash
pip install sqlalchemy
# 根据数据库选择驱动
pip install psycopg2-binary     # PostgreSQL
pip install pymysql             # MySQL
pip install aiosqlite           # SQLite 异步(可选)

三、快速开始(SQLAlchemy 2.0 风格)

1. 创建引擎与基类

python
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, sessionmaker, Mapped, mapped_column

# 数据库连接地址
DATABASE_URL = "sqlite:///./test.db"
# PostgreSQL 示例:postgresql://user:password@localhost/dbname

engine = create_engine(
    DATABASE_URL,
    echo=True,              # 打印实际执行的 SQL(开发时建议开启)
)

class Base(DeclarativeBase):
    pass

# 创建 Session 工厂
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)

2. 定义模型

python
from datetime import datetime
from sqlalchemy import String, Integer, DateTime, ForeignKey, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(50), index=True)
    email: Mapped[str] = mapped_column(String(100), unique=True, index=True)
    age: Mapped[int | None] = mapped_column(Integer, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)

    # 一对多关系
    posts: Mapped[list["Post"]] = relationship(back_populates="author")

class Post(Base):
    __tablename__ = "posts"

    id: Mapped[int] = mapped_column(primary_key=True)
    title: Mapped[str] = mapped_column(String(200))
    content: Mapped[str] = mapped_column(Text)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))

    author: Mapped["User"] = relationship(back_populates="posts")

3. 创建表

python
Base.metadata.create_all(bind=engine)

四、最常用的 CRUD 操作

python
from sqlalchemy import select

# 获取 Session
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

1. 增加(Create)

python
db = SessionLocal()

user = User(name="Alice", email="alice@example.com", age=25)
db.add(user)
db.commit()                # 提交事务
db.refresh(user)           # 刷新对象(获取数据库生成的 id 等)
print(user.id)

# 批量添加
db.add_all([
    User(name="Bob", email="bob@example.com"),
    User(name="Charlie", email="charlie@example.com"),
])
db.commit()

2. 查询(Read)

python
# 查询所有
users = db.scalars(select(User)).all()

# 按主键查询
user = db.get(User, 1)

# 条件查询
stmt = select(User).where(User.age > 20).order_by(User.id.desc())
users = db.scalars(stmt).all()

# 查询第一条
user = db.scalars(select(User).where(User.email == "alice@example.com")).first()

# 只获取部分字段
stmt = select(User.name, User.email)
results = db.execute(stmt).all()

3. 更新(Update)

python
user = db.get(User, 1)
if user:
    user.age = 26
    user.name = "Alice Updated"
    db.commit()

或者使用 update 语句(适合批量):

python
from sqlalchemy import update

stmt = update(User).where(User.id == 1).values(age=26)
db.execute(stmt)
db.commit()

4. 删除(Delete)

python
user = db.get(User, 1)
if user:
    db.delete(user)
    db.commit()

五、关系查询

python
# 创建用户和文章
user = User(name="Alice", email="alice@example.com")
post1 = Post(title="第一篇文章", content="内容...", author=user)
post2 = Post(title="第二篇文章", content="内容...", author=user)

db.add(user)          # 级联添加 posts(需要配置 cascade)
db.commit()

# 查询用户时加载文章
user = db.scalars(select(User).where(User.id == 1)).first()
print(user.posts)     # 自动加载相关文章(默认 lazy)

常用关系加载策略:

  • lazy="select"(默认)
  • lazy="joined"(连表一次加载)
  • lazy="selectin"(推荐,适合一对多)

六、FastAPI 中的典型用法

python
from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.orm import Session

app = FastAPI()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.post("/users/")
def create_user(name: str, email: str, db: Session = Depends(get_db)):
    user = User(name=name, email=email)
    db.add(user)
    db.commit()
    db.refresh(user)
    return user

@app.get("/users/{user_id}")
def read_user(user_id: int, db: Session = Depends(get_db)):
    user = db.get(User, user_id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user

七、事务与异常处理

python
db = SessionLocal()
try:
    user = User(name="Alice", email="alice@example.com")
    db.add(user)
    db.commit()
except Exception:
    db.rollback()          # 出错回滚
    raise
finally:
    db.close()

在 FastAPI 的依赖中,通常把 commit 放在业务逻辑成功后,异常时自动回滚。

八、Alembic 数据库迁移(强烈建议)

直接 create_all 只适合开发阶段。生产环境应使用 Alembic 做版本化迁移。

bash
pip install alembic
alembic init alembic

常用命令:

bash
alembic revision --autogenerate -m "create users table"
alembic upgrade head
alembic downgrade -1

九、最佳实践

  1. 使用 SQLAlchemy 2.0 风格Mappedmapped_columnselect()
  2. Session 生命周期要短,不要长期持有
  3. 生产环境关闭 echo=True
  4. 合理使用索引(index=Trueunique=True
  5. 关系加载注意 N+1 问题,必要时用 selectinloadjoinedload
  6. 密码等敏感字段不要明文存储
  7. 大型项目推荐把 Model、Session、CRUD 分层
  8. 优先使用 Alembic 管理表结构变更

十、Core 与 ORM 如何选择?

  • ORM:开发速度快,适合大多数业务系统
  • Core:需要极致性能、复杂 SQL、批量操作时更合适

两者可以在同一项目中混合使用。