SQLAlchemy 推荐使用 Core 的 insert().returning() 实现跨数据库插入后返回自增 ID,PostgreSQL 原生支持,MySQL 8.0.19+ 配合新驱动也支持;ORM 则通过 session.flush() 后直接读取主键。

SQLAlchemy 提供了统一的写法来实现“插入后返回自增 ID”,无需为 MySQL 和 PostgreSQL 分别写逻辑,关键在于正确使用 insert().returning()(现代 Core)或 ORM 的 session.flush() + 主键属性(传统 ORM),并配合数据库驱动支持。
推荐方式:使用 Core 的 insert().returning()
这是最直接、跨数据库兼容性最好的方法(PostgreSQL 原生支持,MySQL 8.0.19+ 也支持 RETURNING)。只需确保使用较新版本的 SQLAlchemy(≥1.4)和对应驱动(如 pymysql ≥1.0 或 mysqlclient ≥2.1,psycopg2 ≥2.8):
- PostgreSQL 自动启用
RETURNING - MySQL 在满足条件(8.0.19+ + 启用
RETURNING支持的驱动)时也会走原生RETURNING;否则 SQLAlchemy 会自动回退到lastrowid方式(仍能拿到 ID,只是非单条语句)
示例(Core):
from sqlalchemy import insert, create_engine from mymodels import users # 假设是 Table 对象stmt = insert(users).values(name="Alice").returning(users.c.id) result = conn.execute(stmt) new_id = result.scalar_one() # 返回单个值(即 id)
ORM 方式:提交前 flush,直接读主键
对 ORM 模型实例,不需要手动写 SQL。只要主键列声明了 primary_key=True 且未显式赋值,SQLAlchemy 会在 session.flush() 后自动填充自增 ID(底层调用 cursor.lastrowid 或 RETURNING):
- MySQL:依赖驱动的
lastrowid(如pymysql的cursor.lastrowid) - PostgreSQL:优先用
RETURNING,fallback 到pg_get_last_oid()或序列查询
示例(ORM):
from mymodels import Useruser = User(name="Bob") session.add(user) session.flush() # 不提交,但已执行 INSERT 并获取 id print(user.id) # 此时 id 已被赋值
session.commit() // 按需提交
注意驱动与方言兼容性
某些旧驱动或配置可能导致 RETURNING 不生效,可显式检查行为:
- 确认 MySQL 版本 ≥8.0.19 且连接 URL 中未禁用(如避免加
?use_returning=false) - PostgreSQL 推荐用
psycopg2(asyncpg也支持RETURNING) - 若用 SQLite,
RETURNING不可用,但lastrowid依然可靠
可通过 engine.dialect.supports_sane_rowcount_returning 查看是否启用原生 RETURNING。
不推荐:手写 SELECT LAST_INSERT_ID() 或 SELECT currval()
这类写法破坏可移植性,且易出错(如事务隔离、多线程竞争、序列名硬编码等)。SQLAlchemy 已封装好适配逻辑,直接信任其 flush() 或 returning() 即可。










