SQLAlchemy 模块使用详解
本文将从核心概念、安装配置、SQL 表达式语言、ORM 框架、高级特性等方面详细讲解 SQLAlchemy 的使用。
一、核心概念
在使用 SQLAlchemy 前,需先理解其核心组件:
-
Engine:数据库引擎,负责管理数据库连接池,是 SQLAlchemy 与数据库的交互入口。
-
Connection:数据库连接,由 Engine 创建,用于执行 SQL 语句。
-
Session:ORM 的会话对象,负责管理对象的生命周期(增删改查),是 ORM 操作的核心。
-
MetaData:元数据对象,用于存储数据库表的结构信息(表、列、约束等)。
-
Table:表示数据库中的表,通过 MetaData 定义。
-
Mapper:将 Python 类映射到数据库表的组件(ORM 核心)。
-
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 官方迁移工具)进行数据迁移。
-
安装 Alembic:
pip install alembic -
初始化迁移环境:
alembic init alembic -
修改
alembic.ini中的数据库连接字符串 -
修改
alembic/env.py中的target_metadata为模型的Base.metadata -
创建迁移脚本:
alembic revision --autogenerate -m "add column to users" -
执行迁移:
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:适合大多数业务开发,通过面向对象的方式操作数据库,降低开发成本,提高代码可维护性。
核心使用流程:
-
安装 SQLAlchemy 和数据库驱动。
-
创建 Engine,配置数据库连接。
-
定义表结构(Core:MetaData+Table;ORM:declarative_base + 模型类)。
-
通过 Connection(Core)或 Session(ORM)执行 CRUD 操作。
-
结合高级特性(事务、关联关系、迁移)完成复杂业务开发。
SQLAlchemy 的优势在于跨数据库兼容性、灵活的 SQL 构造、强大的 ORM 功能

浙公网安备 33010602011771号