RETURNING 是什么
PostgreSQL 的 INSERT、UPDATE、DELETE 都支持 RETURNING 子句,执行完成后直接返回受影响行的数据,省掉一次回查。MySQL 没有 RETURNING,插入后只能取自增主键,其它列要再查一次。
基本信息
| PostgreSQL 支持 | INSERT、UPDATE、DELETE 都可以带 RETURNING |
|---|---|
| 返回内容 | 可以是列、表达式,也可用 old.* 与 new.* |
| MySQL 替代 | 插入后 SELECT LAST_INSERT_ID(),其它列需要回查 |
| 事务语义 | 返回值由本语句自己产生,不受并发插入影响 |
| 批量插入 | 逐行返回,数据量大时注意结果集规模 |
| 配合 CTE | WITH … INSERT … RETURNING 可把结果继续用于后续语句 |
PostgreSQL 三种用法
PostgreSQL 三种用法
INSERT INTO users (name) VALUES ('alice')
RETURNING id, created_at; -- 插入后立刻拿到主键与默认值
UPDATE orders SET status = 'paid' WHERE id = 1
RETURNING id, status; -- 更新后拿到最终状态
DELETE FROM sessions WHERE expire_at < now()
RETURNING id; -- 删除后拿到被删记录的 id 列表MySQL 的替代方案
MySQL 的替代方案
INSERT INTO users (name) VALUES ('alice');
SELECT LAST_INSERT_ID(); -- 只能拿到自增主键
-- 其它列(默认值、触发器写入的值)需要回查一次
SELECT id, created_at FROM users WHERE id = LAST_INSERT_ID();
-- 这两步必须在同一条连接上执行,连接池下尤其注意能力对照
| 能力 | PostgreSQL | MySQL 8 |
|---|---|---|
| INSERT 返回行 | RETURNING | 不支持,用 LAST_INSERT_ID 或回查 |
| UPDATE 返回行 | RETURNING | 不支持,需要回查 |
| DELETE 返回行 | RETURNING | 不支持,删除前先 SELECT 存档 |
| 返回计算值 | 支持表达式 | 不支持 |
| 批量插入返回值 | 逐行返回 | 只返回首个自增值 |
典型使用场景
- 下单后立即拿到订单号与创建时间写入日志
- 清理任务:删除时记录被删的 id 清单
- 状态变更后把新值推送给下游
- 批量导入后回收全部主键做后续关联
- 数据修复:更新后核对实际被改动的行
- 幂等接口:插入成功时返回生成的主键给调用方
RETURNING 与写入在同一语句里完成,因此不会出现“插入后再查,结果被别的事务抢先”的问题,这正是它比回查更安全的地方。
从 PostgreSQL 迁到 MySQL 时这里最容易漏改:继续用“插入后再查一次”的模式,并发下会取到别人的行,必须改成连接级函数,或重新设计取值流程。