postgresql 中 insert ... returning 可一次性插入并返回新生成字段,如 returning id;mysql 用 last_insert_id();sql server 用 output inserted.id;sqlite 3.35.0+ 支持 returning。

INSERT ... RETURNING 在 PostgreSQL 中怎么用
PostgreSQL 支持 INSERT ... RETURNING 语法,能一次性插入数据并拿到刚生成的字段(比如自增 ID、默认值、计算列)。这是最直接的方案,不用额外查一次。
常见错误是把它当成 MySQL 或 SQL Server 的写法——它们不支持 RETURNING,硬写会报错 syntax error at or near "RETURNING"。
-
RETURNING *返回整行,适合需要全部字段的场景;只返回关键字段更轻量,比如RETURNING id, created_at - 如果表有
serial或IDENTITY主键,RETURNING id就能立刻拿到新记录 ID - 注意:在事务中执行时,
RETURNING返回的是已写入但尚未提交的数据,其他会话不可见
MySQL 怎么实现类似效果
MySQL 没有 RETURNING,得靠 LAST_INSERT_ID() 配合 AUTO_INCREMENT 主键。前提是插入语句没显式指定主键值,且用的是单条 INSERT(批量插入只返回第一个 ID)。
容易踩的坑是用了 INSERT ... ON DUPLICATE KEY UPDATE ——这时 LAST_INSERT_ID() 可能返回 0 或旧 ID,行为不可靠。
- 执行
INSERT INTO users (name, email) VALUES ('Alice', 'a@example.com') - 紧接着查
SELECT LAST_INSERT_ID(),结果就是新记录的id - 如果用连接池(如 Python 的
pymysql),必须保证两次操作在同一个连接上,否则取不到正确值
SQL Server 的 OUTPUT 子句怎么写
SQL Server 用 OUTPUT 实现类似功能,语法比 PostgreSQL 略啰嗦,但支持更灵活的输出目标(比如插入到临时表)。
典型错误是把 OUTPUT 放在 VALUES 后面却忘了加括号,或误写成 RETURNING 导致语法报错 Incorrect syntax near 'OUTPUT'。
INSERT INTO users (name, email) OUTPUT INSERTED.id, INSERTED.created_at VALUES ('Bob', 'b@example.com')-
INSERTED是关键字,表示新插入的行;对应还有DELETED(用于UPDATE/DELETE) - 不能单独执行
OUTPUT,必须依附于INSERT/UPDATE/DELETE语句
跨数据库的兼容性处理建议
如果代码要适配多种数据库,别指望一条 SQL 通吃。ORM(如 SQLAlchemy、Django ORM)内部做了封装,但裸写 SQL 时得按方言分支处理。
最容易被忽略的是:有些场景根本不需要返回 ID ——比如日志表、事件表,插入后压根不关心主键,强行查反而增加延迟和锁竞争。
- PostgreSQL:优先用
RETURNING - MySQL:依赖
LAST_INSERT_ID(),确认主键是AUTO_INCREMENT且未手动赋值 - SQL Server:用
OUTPUT,注意INSERTED前缀不能省 - SQLite:支持
RETURNING(3.35.0+),但旧版本只能用last_insert_rowid()











