SQLAlchemy 模块使用详解

SQLAlchemy 是 Python 中最流行的 ORM(对象关系映射)工具之一,它提供了SQL 表达式语言和ORM 框架双重能力,既可以像原生 SQL 一样灵活操作数据库,又能通过面向对象的方式管理数据库表和数据,支持 MySQL、PostgreSQL、SQLite、Oracle 等主流数据库。

本文将从核心概念、安装配置、SQL 表达式语言、ORM 框架、高级特性等方面详细讲解 SQLAlchemy 的使用。

一、核心概念

在使用 SQLAlchemy 前,需先理解其核心组件:

  1. Engine:数据库引擎,负责管理数据库连接池,是 SQLAlchemy 与数据库的交互入口。

  2. Connection:数据库连接,由 Engine 创建,用于执行 SQL 语句。

  3. Session:ORM 的会话对象,负责管理对象的生命周期(增删改查),是 ORM 操作的核心。

  4. MetaData:元数据对象,用于存储数据库表的结构信息(表、列、约束等)。

  5. Table:表示数据库中的表,通过 MetaData 定义。

  6. Mapper:将 Python 类映射到数据库表的组件(ORM 核心)。

  7. Model:ORM 中的模型类,继承自declarative_base,封装了表结构和业务逻辑。

SQLAlchemy 分为两大使用模式:

  • Core:SQL 表达式语言,偏底层,通过构造 SQL 表达式操作数据库,比原生 SQL 更易维护。

  • ORM:对象关系映射,将 Python 类与数据库表绑定,通过操作对象实现数据库操作,更符合面向对象编程。

二、安装与基础配置

2.1 安装 SQLAlchemy

# 基础安装
pip install sqlalchemy
​
# 安装对应数据库的驱动(以MySQL为例)
pip install pymysql  # MySQL驱动
pip install psycopg2-binary  # PostgreSQL驱动
pip install cx-Oracle  # Oracle驱动

2.2 数据库连接字符串

SQLAlchemy 通过连接字符串指定数据库类型、地址、账号等信息,格式如下:

数据库类型+驱动://用户名:密码@主机:端口/数据库名?参数

常见数据库的连接字符串示例:

数据库连接字符串示例
SQLite sqlite:///test.db(本地文件)/ sqlite:///:memory:(内存数据库)
MySQL mysql+pymysql://root:123456@localhost:3306/test?charset=utf8mb4
PostgreSQL postgresql+psycopg2://postgres:123456@localhost:5432/test

2.3 创建 Engine

Engine 是数据库连接的核心,创建方式如下:

from sqlalchemy import create_engine
​
# 以SQLite为例(无需账号密码,文件自动创建)
engine = create_engine(
   "sqlite:///test.db",
   echo=True,  # 打印生成的SQL语句(调试用)
   pool_size=5,  # 连接池大小
   max_overflow=10  # 连接池最大溢出数
)
​
# 以MySQL为例
# engine = create_engine("mysql+pymysql://root:123456@localhost:3306/test?charset=utf8mb4")
  • echo=True:开启调试模式,控制台会输出 SQLAlchemy 生成的原生 SQL,开发阶段建议开启。

  • 连接池参数:pool_size指定常驻连接数,max_overflow指定临时连接数,默认连接池为QueuePool。

三、SQLAlchemy Core:SQL 表达式语言

Core 模式通过定义表结构、构造 SQL 表达式来操作数据库,适合需要灵活控制 SQL 的场景。

3.1 定义表结构(MetaData + Table)

通过MetaData和Table类定义数据库表,支持列类型、约束(主键、外键、唯一约束等)。

from sqlalchemy import MetaData, Table, Column, Integer, String, Float, ForeignKey
​
# 初始化元数据
metadata = MetaData()
​
# 定义用户表
users = Table(
   "users",  # 表名
   metadata,
   Column("id", Integer, primary_key=True, autoincrement=True),  # 主键,自增
   Column("name", String(50), nullable=False),  # 姓名,非空
   Column("age", Integer, default=0),  # 年龄,默认值0
   Column("email", String(100), unique=True)  # 邮箱,唯一约束
)
​
# 定义订单表(含外键关联用户表)
orders = Table(
   "orders",
   metadata,
   Column("id", Integer, primary_key=True, autoincrement=True),
   Column("user_id", Integer, ForeignKey("users.id"), nullable=False),  # 外键关联users.id
   Column("product", String(100), nullable=False),
   Column("price", Float, nullable=False)
)
​
# 创建所有表(如果表已存在,不会重复创建)
metadata.create_all(engine)

3.2 执行 CRUD 操作

Core 模式通过Connection执行 SQL 表达式,核心操作包括插入、查询、更新、删除。

3.2.1 插入数据(INSERT)

使用insert()构造插入语句,通过execute()执行。

from sqlalchemy import insert
​
# 1. 插入单条数据
with engine.connect() as conn:
   # 构造插入语句
   stmt = insert(users).values(name="张三", age=25, email="zhangsan@example.com")
   # 执行语句并提交
   result = conn.execute(stmt)
   conn.commit()
   print("插入的用户ID:", result.inserted_primary_key[0])  # 获取自增主键
​
# 2. 插入多条数据
with engine.connect() as conn:
   stmt = insert(users).values([
      {"name": "李四", "age": 30, "email": "lisi@example.com"},
      {"name": "王五", "age": 28, "email": "wangwu@example.com"}
  ])
   conn.execute(stmt)
   conn.commit()

3.2.2 查询数据(SELECT)

使用select()构造查询语句,支持条件过滤、联表、排序、分页等。

from sqlalchemy import select, and_, or_
​
# 1. 查询所有用户
with engine.connect() as conn:
   stmt = select(users)
   result = conn.execute(stmt)
   # 获取所有结果(元组形式)
   all_users = result.fetchall()
   for user in all_users:
       print(user)  # (1, '张三', 25, 'zhangsan@example.com')
​
# 2. 条件查询(年龄>25且姓名含"李")
with engine.connect() as conn:
   stmt = select(users).where(
       and_(users.c.age > 25, users.c.name.like("%李%"))
  )
   result = conn.execute(stmt)
   print(result.fetchone())  # 获取单条结果
​
# 3. 联表查询(用户表+订单表)
with engine.connect() as conn:
   stmt = select(users.c.name, orders.c.product, orders.c.price).join(orders, users.c.id == orders.c.user_id)
   result = conn.execute(stmt)
   for row in result:
       print(f"用户:{row.name},商品:{row.product},价格:{row.price}")
​
# 4. 排序与分页
with engine.connect() as conn:
   stmt = select(users).order_by(users.c.age.desc()).offset(0).limit(2)  # 按年龄降序,取前2条
   result = conn.execute(stmt)
   print(result.fetchall())
  • users.c.age:c是Column的缩写,代表表的列。

  • 条件运算符:==、!=、>、<、like()、in_()等;逻辑运算符:and_()、or_()、not_()。

3.2.3 更新数据(UPDATE)

使用update()构造更新语句,结合where()指定更新条件。

from sqlalchemy import update
​
with engine.connect() as conn:
   # 将张三的年龄改为26
   stmt = update(users).where(users.c.name == "张三").values(age=26)
   result = conn.execute(stmt)
   conn.commit()
   print("更新的行数:", result.rowcount)  # 获取受影响的行数

3.2.4 删除数据(DELETE)

使用delete()构造删除语句,结合where()指定删除条件。

from sqlalchemy import delete
​
with engine.connect() as conn:
   # 删除邮箱为wangwu@example.com的用户
   stmt = delete(users).where(users.c.email == "wangwu@example.com")
   result = conn.execute(stmt)
   conn.commit()
   print("删除的行数:", result.rowcount)

四、SQLAlchemy ORM:对象关系映射

ORM 模式将 Python 类与数据库表绑定,通过操作模型对象实现数据库操作,更符合面向对象的开发习惯,是 SQLAlchemy 的核心使用方式。

4.1 定义 ORM 模型

通过declarative_base()创建基类,模型类继承该基类,直接在类中定义表结构。

from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy import Column, Integer, String, Float, ForeignKey
​
# 创建ORM基类
Base = declarative_base()
​
# 定义用户模型
class User(Base):
   __tablename__ = "users"  # 表名
​
   # 列定义
   id = Column(Integer, primary_key=True, autoincrement=True)
   name = Column(String(50), nullable=False)
   age = Column(Integer, default=0)
   email = Column(String(100), unique=True)
​
   # 关联订单(一对多):一个用户对应多个订单
   orders = relationship("Order", back_populates="user", cascade="all, delete-orphan")
​
   # 自定义打印格式
   def __repr__(self):
       return f"<User(id={self.id}, name={self.name}, age={self.age})>"
​
# 定义订单模型
class Order(Base):
   __tablename__ = "orders"
​
   id = Column(Integer, primary_key=True, autoincrement=True)
   user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
   product = Column(String(100), nullable=False)
   price = Column(Float, nullable=False)
​
   # 关联用户(多对一):多个订单对应一个用户
   user = relationship("User", back_populates="orders")
​
   def __repr__(self):
       return f"<Order(id={self.id}, product={self.product}, price={self.price})>"
​
# 创建所有表(如果表已存在,不会重复创建)
Base.metadata.create_all(engine)
  • relationship:定义模型间的关联关系(一对多、多对一、多对多),back_populates指定反向关联。

  • cascade:级联操作,如all, delete-orphan表示删除用户时自动删除其关联的订单。

4.2 创建 Session 会话

ORM 操作的核心是Session,通过sessionmaker创建会话工厂:

from sqlalchemy.orm import sessionmaker
​
# 创建会话工厂
Session = sessionmaker(bind=engine)
​
# 生成会话对象(每次操作数据库时创建)
session = Session()

4.3 执行 CRUD 操作

ORM 模式通过操作模型对象和Session实现数据库操作,无需编写 SQL 表达式。

4.3.1 插入数据(新增对象)

创建模型对象,通过session.add()/session.add_all()添加,session.commit()提交。

# 1. 插入单条数据
user1 = User(name="赵六", age=35, email="zhaoliu@example.com")
session.add(user1)
session.commit()
print("插入的用户ID:", user1.id)  # 提交后自动获取自增主键
​
# 2. 插入多条数据
user2 = User(name="孙七", age=22, email="sunqi@example.com")
user3 = User(name="周八", age=40, email="zhouba@example.com")
session.add_all([user2, user3])
session.commit()
​
# 3. 插入关联数据(用户+订单)
user4 = User(name="吴九", age=27, email="wujiu@example.com")
# 创建订单并关联用户
order1 = Order(product="手机", price=2999, user=user4)
order2 = Order(product="电脑", price=5999, user=user4)
session.add(user4)
session.commit()
print("用户的订单:", user4.orders)  # 通过关联属性获取订单

4.3.2 查询数据(查询对象)

使用session.query()构造查询,支持条件过滤、联表、排序、分页等,返回结果为模型对象。

# 1. 查询所有用户
all_users = session.query(User).all()
for user in all_users:
   print(user)  # <User(id=1, name=张三, age=26)>
​
# 2. 查询单条数据(按主键/条件)
user = session.query(User).get(1)  # 按主键查询
print("按主键查询:", user)
​
user = session.query(User).filter(User.name == "李四").first()  # 按条件查询第一条
print("按条件查询:", user)
​
# 3. 条件过滤(多条件、模糊查询)
users = session.query(User).filter(
   User.age > 25,
   User.email.like("%example.com%")
).all()
print("多条件查询:", users)
​
# 4. 联表查询(通过关联属性)
orders = session.query(Order).join(User).filter(User.name == "吴九").all()
for order in orders:
   print(f"用户:{order.user.name},订单:{order.product}")
​
# 5. 排序与分页
users = session.query(User).order_by(User.age.desc()).offset(0).limit(2).all()
print("排序分页:", users)
​
# 6. 聚合查询(计数、求和、平均值)
from sqlalchemy import func
​
# 统计用户总数
count = session.query(func.count(User.id)).scalar()
print("用户总数:", count)
​
# 统计用户平均年龄
avg_age = session.query(func.avg(User.age)).scalar()
print("平均年龄:", avg_age)
​
# 统计订单总金额
total_price = session.query(func.sum(Order.price)).scalar()
print("订单总金额:", total_price)
  • filter():指定查询条件,支持链式调用;filter_by():简化条件(仅支持关键字参数),如filter_by(name="张三")。

  • all():返回所有结果;first():返回第一条;scalar():返回单个值(聚合查询)。

4.3.3 更新数据(更新对象)

直接修改模型对象的属性,通过session.commit()提交修改。

# 1. 修改单个对象
user = session.query(User).get(1)
user.age = 27  # 直接修改属性
session.commit()
print("更新后的用户:", user)
​
# 2. 批量更新
session.query(User).filter(User.age < 30).update({User.age: User.age + 1})
session.commit()
print("批量更新完成")

4.3.4 删除数据(删除对象)

使用session.delete()删除对象,session.commit()提交删除。

# 1. 删除单个对象
user = session.query(User).get(5)
session.delete(user)
session.commit()
print("删除用户完成")
​
# 2. 批量删除
session.query(Order).filter(Order.price < 3000).delete()
session.commit()
print("批量删除订单完成")

4.4 关闭会话

操作完成后,需关闭会话释放资源:

session.close()

五、高级特性

5.1 事务管理

SQLAlchemy 的Session和Connection默认支持事务,通过rollback()回滚事务。

# ORM事务示例
session = Session()
try:
   user = User(name="测试用户", age=20, email="test@example.com")
   session.add(user)
   # 模拟异常
   1 / 0
   session.commit()
except Exception as e:
   session.rollback()  # 回滚事务
   print("事务回滚:", e)
finally:
   session.close()

5.2 多对多关系

多对多关系需要中间表,通过relationship的secondary参数指定中间表。

# 定义中间表(用户-角色)
user_role = Table(
   "user_role",
   Base.metadata,
   Column("user_id", Integer, ForeignKey("users.id"), primary_key=True),
   Column("role_id", Integer, ForeignKey("roles.id"), primary_key=True)
)
​
# 定义角色模型
class Role(Base):
   __tablename__ = "roles"
   id = Column(Integer, primary_key=True, autoincrement=True)
   name = Column(String(50), unique=True)
   # 多对多关联用户
   users = relationship("User", secondary=user_role, back_populates="roles")
​
# 修改User模型,添加多对多关联
class User(Base):
   __tablename__ = "users"
   # 原有列定义...
   roles = relationship("Role", secondary=user_role, back_populates="users")
​
# 创建表
Base.metadata.create_all(engine)
​
# 插入多对多数据
role1 = Role(name="管理员")
role2 = Role(name="普通用户")
user = User(name="管理员用户", age=30, email="admin@example.com")
user.roles = [role1, role2]
session.add(user)
session.commit()
print("用户的角色:", user.roles)

5.3 数据迁移

当模型结构发生变化时(如新增列、修改约束),需使用Alembic(SQLAlchemy 官方迁移工具)进行数据迁移。

  1. 安装 Alembic:pip install alembic

  2. 初始化迁移环境:alembic init alembic

  3. 修改alembic.ini中的数据库连接字符串

  4. 修改alembic/env.py中的target_metadata为模型的Base.metadata

  5. 创建迁移脚本:alembic revision --autogenerate -m "add column to users"

  6. 执行迁移:alembic upgrade head

5.4 懒加载与立即加载

ORM 的关联关系默认是懒加载(Lazy Loading),即访问关联属性时才会查询数据库。可通过lazy参数修改加载策略:

  • lazy="select":默认,懒加载。

  • lazy="joined":立即加载(联表查询)。

  • lazy="subquery":子查询加载。

  • lazy="dynamic":返回查询对象,支持后续过滤。

示例:

# 立即加载用户的订单
class User(Base):
   __tablename__ = "users"
   # 原有列定义...
   orders = relationship("Order", back_populates="user", lazy="joined")

六、总结

SQLAlchemy 提供了Core和ORM两种使用模式,满足不同场景的需求:

  • Core:适合需要灵活控制 SQL 的场景,如复杂查询、高性能操作,是 ORM 的底层支撑。

  • ORM:适合大多数业务开发,通过面向对象的方式操作数据库,降低开发成本,提高代码可维护性。

核心使用流程:

  1. 安装 SQLAlchemy 和数据库驱动。

  2. 创建 Engine,配置数据库连接。

  3. 定义表结构(Core:MetaData+Table;ORM:declarative_base + 模型类)。

  4. 通过 Connection(Core)或 Session(ORM)执行 CRUD 操作。

  5. 结合高级特性(事务、关联关系、迁移)完成复杂业务开发。

SQLAlchemy 的优势在于跨数据库兼容性、灵活的 SQL 构造、强大的 ORM 功能,是 Python 后端开发中操作数据库的首选工具之一。

posted @ 2025-12-18 11:02  gugucai  阅读(126)  评论(0)    收藏  举报