首页/数据/SQL 速查/RETURNING 返回插入结果(PostgreSQL)
变更与事务52 条

RETURNING 返回插入结果(PostgreSQL)

插入/更新/删除后直接返回受影响的行数据:PostgreSQL 全支持;MySQL 没有 RETURNING,只能取自增 ID。

SQL 速查数据更新于 2026-10-13

RETURNING 是什么

PostgreSQL 的 INSERT、UPDATE、DELETE 都支持 RETURNING 子句,执行完成后直接返回受影响行的数据,省掉一次回查。MySQL 没有 RETURNING,插入后只能取自增主键,其它列要再查一次。

基本信息

PostgreSQL 支持INSERT、UPDATE、DELETE 都可以带 RETURNING
返回内容可以是列、表达式,也可用 old.* 与 new.*
MySQL 替代插入后 SELECT LAST_INSERT_ID(),其它列需要回查
事务语义返回值由本语句自己产生,不受并发插入影响
批量插入逐行返回,数据量大时注意结果集规模
配合 CTEWITH … 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();
-- 这两步必须在同一条连接上执行,连接池下尤其注意

能力对照

能力PostgreSQLMySQL 8
INSERT 返回行RETURNING不支持,用 LAST_INSERT_ID 或回查
UPDATE 返回行RETURNING不支持,需要回查
DELETE 返回行RETURNING不支持,删除前先 SELECT 存档
返回计算值支持表达式不支持
批量插入返回值逐行返回只返回首个自增值

典型使用场景

  • 下单后立即拿到订单号与创建时间写入日志
  • 清理任务:删除时记录被删的 id 清单
  • 状态变更后把新值推送给下游
  • 批量导入后回收全部主键做后续关联
  • 数据修复:更新后核对实际被改动的行
  • 幂等接口:插入成功时返回生成的主键给调用方
RETURNING 与写入在同一语句里完成,因此不会出现“插入后再查,结果被别的事务抢先”的问题,这正是它比回查更安全的地方。
从 PostgreSQL 迁到 MySQL 时这里最容易漏改:继续用“插入后再查一次”的模式,并发下会取到别人的行,必须改成连接级函数,或重新设计取值流程。

易错点

  • MySQL 里想用 RETURNING:语法直接报错,需要按版本能力改写成回查方案
  • 把回查语句放到另一条连接上:连接池里会取到 0 或别人的主键
  • 批量 RETURNING 结果集过大:几万行一次性返回会占用大量内存与网络,按批处理
  • 以为回查能拿到默认值:默认值、触发器写入的值需要额外查询,多一次往返也多一次不一致风险

数据来源与参考

  • PostgreSQL Documentation · INSERT
  • MySQL 8.0 Reference Manual · INSERT
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌