跳到主要内容 Python 使用 SQLAlchemy 操作 MySQL 入门与实战 | 极客日志
Python
Python 使用 SQLAlchemy 操作 MySQL 入门与实战 SQLAlchemy 是 Python 生态中广泛使用的 ORM 框架,支持多种数据库。本文详细讲解基于 SQLAlchemy 和 MySQL 的环境搭建流程,包括 Docker 部署 MySQL 及依赖库安装。核心部分涵盖 Engine 连接池管理、Base 模型定义及 Session 会话操作。通过 User 和 Order 表示例,演示了完整的增删改查逻辑及一对多关系映射实现。此外还包含连接池参数优化、防止 SQL 注入的安全实践以及事务处理机制。文末提供常见报错解决方案及 Alembic 迁移工具的学习建议,帮助开发者高效构建数据持久层。
SQLAlchemy 是 Python 生态中广泛使用的 ORM 框架,支持多种数据库。本文将介绍如何使用 SQLAlchemy 连接 MySQL,涵盖环境搭建、核心概念、CRUD 实战及关系映射。
一、前置准备:环境配置
在写代码前,需完成以下配置:安装 MySQL、安装 Python 库、配置连接。
1. 安装 MySQL
推荐使用 Docker 部署 MySQL 以简化环境配置:
docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0
验证是否启动成功:
docker ps
2. 安装 Python 依赖库
pymysql:Python 连接 MySQL 的驱动;
sqlalchemy:核心 ORM 框架。
pip install pymysql sqlalchemy
3. 测试 MySQL 连接 from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:root123@localhost:3306/test_db' )
with engine.connect() as conn:
print ("连接成功!" )
连接字符串中的 test_db 需要先在 MySQL 中创建(用 Navicat 或命令行 CREATE DATABASE test_db;);
如果用本地 MySQL 而非 Docker,host 填 localhost,密码填安装时设置的密码。
二、SQLAlchemy 核心概念 SQLAlchemy 的核心是'用对象封装数据库操作',主要包含 3 个关键组件:
1. Engine:数据库连接的'总开关'
作用 :管理数据库连接池(不用每次操作都新建连接,提升性能);
类比 :像家里的'总电源开关',控制所有电器的供电。
from sqlalchemy import create_engine
engine = create_engine(
'mysql+pymysql://root:root123@localhost:3306/test_db' ,
echo=True ,
pool_size=5 ,
max_overflow=10
)
2. Base:所有模型的'模板'
作用 :定义模型类的基类,自动映射类到数据库表;
类比 :像'建筑图纸',所有房子(模型类)都基于这个图纸建造。
from sqlalchemy.orm import declarative_base
Base = declarative_base()
3. Session:操作数据库的'把手'
作用 :负责和数据库交互(新增、查询、更新、删除);
类比 :像'遥控器',通过它控制电视(数据库)的操作。
from sqlalchemy.orm import sessionmaker
SessionLocal = sessionmaker(bind=engine)
session = SessionLocal()
总结 :Engine→连接池→Session→操作数据库;Base→模型类→表结构。
三、实战 1:定义第一个模型类 ——User 表 现在,我们用 Base 定义一个 User 类,对应 MySQL 的 users 表。
1. 定义模型类 from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.sql import func
from datetime import datetime
class User (Base ):
__tablename__ = 'users'
id = Column(Integer, primary_key=True , index=True )
name = Column(String(50 ), nullable=False )
email = Column(String(100 ), unique=True , index=True )
age = Column(Integer)
created_at = Column(DateTime(timezone=True ), default=func.now())
__tablename__:模型类对应的表名(必须和数据库中的表名一致,MySQL 默认小写);
primary_key=True:标记为主键(自增);
nullable=False:字段非空(插入数据时必须传值);
unique=True:字段唯一(避免重复邮箱);
func.now():用 MySQL 的 NOW() 函数自动填充当前时间(比 Python 的 datetime.now() 更准确)。
2. 创建表结构
Base.metadata.create_all(bind=engine)
这段代码只会创建不存在的表(不会覆盖已有表);
如果修改了模型类(比如新增字段),需要用迁移工具(如 Alembic)更新表结构(本文暂不展开)。
四、实战 2:CRUD 操作 现在,我们用 Session 实现增删改查,全程不用写 SQL!
1. 新增数据(Create)
user = User(name='张三' , email='[email protected] ' , age=18 )
session.add(user)
session.commit()
session.refresh(user)
print (f"新增用户 ID:{user.id } " )
add() 只是将数据'暂存'到 Session,必须 commit() 才会写入数据库 ;
refresh() 会从数据库中获取最新数据(比如自增的 id)。
2. 查询数据(Read) SQLAlchemy 提供了强大的查询 API,常用的有:
(1)根据主键查询(最常用)
user = session.get(User, 1 )
if user:
print (f"用户姓名:{user.name} ,邮箱:{user.email} " )
else :
print ("用户不存在" )
(2)条件查询(比如查年龄≥18 的用户) from sqlalchemy import select
stmt = select(User).where(User.age >= 18 )
users = session.execute(stmt).scalars().all ()
for user in users:
print (f"ID:{user.id } ,姓名:{user.name} " )
(3)模糊查询(比如查姓名包含'张'的用户) stmt = select(User).where(User.name.like('%张%' ))
users = session.execute(stmt).scalars().all ()
3. 更新数据(Update)
user = session.get(User, 1 )
user.age = 20
user.email = '[email protected] '
session.commit()
4. 删除数据(Delete)
user = session.get(User, 1 )
session.delete(user)
session.commit()
五、实战 3:关系映射 实际项目中,表之间一定有关系(比如用户和订单的'一对多'),SQLAlchemy 能自动处理这些关系。
1. 定义关联模型(比如 Order 表) class Order (Base ):
__tablename__ = 'orders'
id = Column(Integer, primary_key=True , index=True )
user_id = Column(Integer, ForeignKey('users.id' ))
product = Column(String(100 ), nullable=False )
price = Column(Integer, nullable=False )
created_at = Column(DateTime(timezone=True ), default=func.now())
user = relationship('User' , back_populates='orders' )
2. 在 User 表中添加反向关系 class User (Base ):
__tablename__ = 'users'
orders = relationship('Order' , back_populates='user' )
3. 测试关系映射
user = User(name='李四' , email='[email protected] ' , age=25 )
session.add(user)
session.commit()
order1 = Order(user_id=user.id , product='手机' , price=5999 )
order2 = Order(user_id=user.id , product='电脑' , price=9999 )
session.add_all([order1, order2])
session.commit()
user = session.get(User, user.id )
for order in user.orders:
print (f"订单 ID:{order.id } ,商品:{order.product} ,价格:{order.price} " )
ForeignKey('users.id'):Order 表的 user_id 关联 User 表的 id(外键约束);
relationship:定义模型之间的关系(比如 User 的 orders 属性会自动查询该用户的所有订单);
back_populates:双向关联(User 的 orders 和 Order 的 user 互相引用)。
六、进阶优化与注意事项
1. 连接池配置(提升性能) Engine 默认开启连接池(大小 5),可以通过 create_engine 的参数优化:
engine = create_engine(
'mysql+pymysql://root:root123@localhost:3306/test_db' ,
pool_size=10 ,
max_overflow=20 ,
pool_timeout=30 ,
pool_recycle=1800
)
2. 避免 SQL 注入(安全第一) SQLAlchemy 的 query 和 execute 方法会自动处理 SQL 注入(用参数化查询),禁止手动拼接 SQL !
name = "张三'; DROP TABLE users; --"
session.execute(f"SELECT * FROM users WHERE name='{name} '" )
from sqlalchemy import text
name = "张三'; DROP TABLE users; --"
stmt = text("SELECT * FROM users WHERE name=:name" )
session.execute(stmt, {"name" : name})
3. 事务处理(避免数据不一致) SQLAlchemy 的 Session 默认开启事务,必须 commit() 才会提交 ,rollback() 可以回滚:
try :
user = User(name='王五' , email='[email protected] ' )
session.add(user)
1 / 0
session.commit()
except Exception as e:
session.rollback()
print (f"错误:{e} " )
七、常见问题解答
1. 连接报错 'Access denied for user 'root'@'localhost''
原因:密码错误或用户没有权限;
解决:检查连接字符串中的密码,或在 MySQL 中给 root 用户授权:
GRANT ALL PRIVILEGES ON * .* TO 'root' @'%' IDENTIFIED BY 'root123' WITH GRANT OPTION;
FLUSH PRIVILEGES;
原因:邮箱重复(unique=True 约束);
解决:确保插入的邮箱唯一,或在代码中处理重复错误。
3. 查询结果为空,但数据库中有数据
原因:index=True 需要先创建索引(或模型类的 __tablename__ 写错);
解决:检查模型类的 __tablename__ 是否和数据库表名一致,或重新创建表(Base.metadata.drop_all() → Base.metadata.create_all())。
八、总结 SQLAlchemy 是 Python 中最常用的 ORM 框架之一,其优势包括:
跨数据库支持 :支持 MySQL、PostgreSQL、SQLite 等,切换数据库只需修改连接字符串;
强大的查询 API :支持复杂查询(联表、分组、排序),不用写 SQL;
事务管理 :自动处理事务,避免数据不一致;
性能优化 :连接池、索引、延迟加载等功能提升性能。
中大型项目(需要复杂的数据库操作);
多数据库切换(比如从 SQLite 迁移到 MySQL);
需要事务管理和安全的项目(比如电商、金融)。
九、后续学习建议
学习 Alembic :数据库迁移工具(修改模型类后,自动更新表结构);
学习 SQLAlchemy Core :直接写 SQL 表达式(比 ORM 更灵活);
学习 查询优化 :比如 joinedload(预加载关联数据,避免 N+1 查询)。
经验总结 :ORM 是工具,不是银弹——简单的查询可以用 ORM,复杂的查询(比如多表联查、统计)建议用 SQLAlchemy Core 或原生 SQL,平衡开发效率和性能。
相关免费在线工具 curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online