用 SQLAlchemy 连 MySQL 需先安装 PyMySQL 驱动,构造 mysql+pymysql:// 格式连接 URL 并编码特殊字符,创建 engine 后立即 connect().close() 验证;Model 定义须明确 primary_key、匹配外键类型、慎用 autoincrement;session.add() 后必须 commit 才生效;复杂查询或 DDL 应改用原生 SQL。

如何用 SQLAlchemy 连上 MySQL 并确认连接有效
直接连不上、报 ModuleNotFoundError: No module named 'pymysql' 或 sqlalchemy.exc.OperationalError 是最常见开头。SQLAlchemy 本身不带 MySQL 驱动,必须额外装适配器。
- 装驱动:运行
pip install pymysql(推荐)或pip install mysqlclient;pymysql纯 Python 实现,免编译,Windows/macOS 更省心 - 构造连接 URL:格式为
mysql+pymysql://user:password@host:port/dbname;密码含特殊字符(如@、/)必须用urllib.parse.quote_plus()编码 - 验证连接:创建
engine = create_engine(url, echo=False)后,立刻执行engine.connect().close(),别等第一次查询才暴露问题
定义 Model 时哪些字段设置容易导致迁移失败
用 Base.metadata.create_all(engine) 自动建表看似方便,但字段定义稍有偏差就会让表结构和预期不符,尤其在已有数据的生产环境不敢轻易重跑。
-
primary_key=True必须明确指定,否则id字段不会自动设为主键,也不会自增 -
autoincrement默认为True,但仅对整数主键生效;若用String类型做主键(如 UUID),得显式写default=uuid4,且不能设autoincrement=True -
nullable=False和数据库 NOT NULL 约束强绑定,但默认值(如default=func.now())只影响 INSERT,不影响 ALTER TABLE 添加列时的非空校验 - 外键字段类型必须和被引用字段**完全一致**:比如被引用的是
Integer,你就不能定义成SmallInteger,否则create_all会静默忽略外键约束
session.add() 后数据没进库?别忘了 commit
新手常以为 session.add() 就等于写入,其实只是把对象标记为“待插入”,真正落库靠 session.commit()。不 commit,事务回滚,什么都没发生。
- 用
try/except包住add+commit,捕获IntegrityError(唯一冲突)、FlushError(未设主键)等异常 -
session.rollback()要紧跟在except里,否则后续操作可能复用已损坏的 session - 批量插入别用多次
add()+commit(),改用session.bulk_save_objects([obj1, obj2]),性能高且避免事务频繁开销 - 如果只是查数据,用
session.execute(select(...))或session.scalars(),不用commit,也别混用session.add()和原生 SQL 执行
什么时候该放弃 ORM,直接写原生 SQL
ORM 对简单 CRUD 很友好,但遇到复杂 JOIN、窗口函数、INSERT … ON DUPLICATE KEY UPDATE、或需要精确控制执行计划时,硬套 ORM 反而绕远路、难调试、性能还差。
立即学习“Python免费学习笔记(深入)”;
- 用
text()执行原生 SQL:session.execute(text("INSERT INTO t (x) VALUES (:val)"), {"val": 42}),参数用命名占位符,防注入 - 读取结果时,别依赖
session.execute(...).scalars()返回模型实例——原生 SQL 返回的是元组或字典,要手动映射 - DDL 操作(如
ALTER TABLE、添加索引)无法用metadata.create_all()覆盖,必须走session.execute(text("...")) - MySQL 的
REPLACE INTO或INSERT ... ON DUPLICATE KEY UPDATE没有对应 ORM 方法,硬写merge()容易覆盖不该覆盖的字段
ORM 不是银弹。字段定义错一点,建表就偏航;session 忘 commit,数据就蒸发;该用原生 SQL 时硬拖 ORM,最后 debug 半天才发现是 SQL 层逻辑卡死。留神那些“默认行为”背后的假设,比记住语法更重要。


















