最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在PostgreSQL中用SQL RETURNING子句获取刚插入行的自增ID?
时间:2026-06-24 08:55:45 编辑:袖梨 来源:一聚教程网
RETURNING必须作为INSERT/UPDATE/DELETE的子句紧随其后,不可单独执行;它支持返回多列、表达式及函数结果,批量插入时返回完整结果集,应用层须完整读取而非仅取首行。
RETURNING 必须跟在 INSERT 之后,不能单独执行
很多人写完 INSERT INTO users (name) VALUES ('Alice'),再另起一行写 RETURNING id,结果报错 ERROR: syntax error at or near "RETURNING"。这是因为 RETURNING 不是独立语句,它必须作为 INSERT(或 UPDATE/DELETE)的子句存在,中间不能换行或加分号隔开。
正确写法只有一条语句:
INSERT INTO users (name) VALUES ('Alice') RETURNING id;
常见错误场景还包括在 ORM 中手动拼 SQL 时漏掉绑定,或者误以为它像 MySQL 的 LAST_INSERT_ID() 可事后调用。
RETURNING 可返回多列、表达式甚至函数结果
不只是主键 ID,RETURNING 能返回插入行的任意列,包括默认值生成的字段(如 created_at)、表达式(如 id * 2),甚至 now() 这类函数(会再次求值,不是插入时的快照)。
- 返回多个字段:
RETURNING id, name, created_at - 返回计算值:
RETURNING id, UPPER(name) AS upper_name - 注意:如果表定义了
DEFAULT now(),RETURNING created_at拿到的是实际插入时的值;但RETURNING now()拿到的是语句执行时刻的时间,二者可能不同
批量 INSERT 时 RETURNING 返回全部插入行的结果集
用 INSERT ... VALUES (...), (...), (...) 或 INSERT ... SELECT 批量插入时,RETURNING 不只返回一行,而是返回一个结果集,每行对应一条插入记录。这点和 MySQL 的单值 LAST_INSERT_ID() 有本质区别。
例如:
INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie') RETURNING id, name;
会返回三行,id 是按插入顺序分配的自增 ID(除非显式指定)。如果业务需要一一对应,别依赖“第一条就是第一个”,而应直接消费整个结果集。
注意:若使用 ON CONFLICT DO NOTHING,被忽略的冲突行不会出现在 RETURNING 结果中;但 ON CONFLICT DO UPDATE RETURNING 会返回更新后的行(含新值)。
在应用代码里获取 RETURNING 结果要读取完整结果集,不能只取第一行
很多开发者用 Python 的 cursor.execute() 执行带 RETURNING 的语句后,直接调 cursor.fetchone() 就认为完事了——这在单行插入时碰巧有效,但一旦改成批量插入,就会丢掉后续所有 ID。
- Python + psycopg2:必须用
cursor.fetchall()或遍历cursor - Node.js + pg:
result.rows是数组,不要只取result.rows[0] - Go + pgx:
rows := pgx.QueryRows()需循环rows.Next()读取全部
更隐蔽的问题是:某些 ORM(如 SQLAlchemy 的 execute())默认不暴露 RETURNING 结果,需显式启用 returning=True 或用 insert().returning() 构造对象。
最易被忽略的一点:事务回滚时,RETURNING 返回的 ID 已被消耗,即使最终没提交,该 ID 也不会复用——PostgreSQL 的序列是预分配且不可逆的。
相关文章
- 天猫双十一大促活动开启 - 2026年超值购物指南 06-24
- 蹭饭网 - 免费美食社交平台 06-24
- 绝地求生PUBG账号购买平台推荐 安全靠谱的买号网站对比 06-24
- 300分左右的优质大专院校推荐 - 2026年高性价比选择 06-24
- 全明星觉醒 进阶全能队阵容搭配与实战攻略 06-24
- 沙石镇时光 知识加点推荐与最优分配方案 06-24