0

0

PostgreSQL插入返回ID怎么实现_PostgreSQL插入返回主键方法

爱谁谁

爱谁谁

发布时间:2025-09-13 11:44:01

|

733人浏览过

|

来源于php中文网

原创

PostgreSQL中推荐使用RETURNING子句在INSERT后直接获取主键,因其确保原子性、避免竞态条件,并减少数据库往返。该方法适用于SERIAL、UUID等主键类型,且可与ON CONFLICT结合实现UPSERT并返回更新后的记录信息,提升效率与代码简洁性。

postgresql插入返回id怎么实现_postgresql插入返回主键方法

在PostgreSQL中,如果你想在执行

INSERT
语句后立即获取新生成的主键(通常是自增ID),最直接且推荐的方法是使用
RETURNING id
子句。这允许你在同一个数据库请求中完成数据插入和ID的检索,非常高效和安全。

在PostgreSQL中,当你需要在一个

INSERT
操作完成后立即获取新生成的主键(通常是序列生成的ID)时,最优雅且推荐的做法是利用
RETURNING
子句。这不仅仅是一种语法糖,它确保了原子性——你的插入和获取ID是同一个事务操作的一部分,避免了潜在的竞态条件或数据不一致问题。

想象一下,你有一个

users
表,其中
id
SERIAL
类型的主键:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE
);

当你插入一条新用户记录时,你只需要在

INSERT
语句的末尾加上
RETURNING id

INSERT INTO users (username, email) VALUES ('alice', 'alice@example.com') RETURNING id;

执行这条语句后,PostgreSQL会直接返回一个结果集,其中包含新插入记录的

id
值。如果你的插入语句是批量操作,例如:

INSERT INTO users (username, email) VALUES
('bob', 'bob@example.com'),
('charlie', 'charlie@example.com')
RETURNING id, username;

它会返回一个包含两行记录的结果集,每行包含对应的

id
username
。这种方式不仅限于
id
,你可以返回任何你需要的列。它的强大之处在于,它将数据插入和结果检索合并成了一个单一的数据库往返(round trip),这对于性能和代码简洁性都非常有益。

为什么推荐使用
RETURNING
子句?它解决了哪些常见痛点?

我个人觉得,

RETURNING
子句在PostgreSQL里真的是一个非常“聪明”的设计。它不仅仅是提供了便利,更重要的是,它从根本上解决了几个在其他数据库系统里可能需要复杂逻辑才能应对的痛点。

最核心的一点是原子性。在没有

RETURNING
的情况下,如果你想获取新插入的ID,你可能需要先
INSERT
,然后紧接着执行一个
SELECT
语句,比如
SELECT id FROM users WHERE username = 'alice' AND email = 'alice@example.com'
。这种“先插后查”的模式,在并发量大的系统里,极易出现问题。想象一下,在你
INSERT
SELECT
之间,可能有另一个事务插入了完全相同的
username
email
(如果这些字段没有唯一约束),或者你查询的条件不够唯一,导致你拿到了错误的ID。
RETURNING
则将这两个操作绑定在一起,确保了你拿到的ID就是你刚刚插入的那条记录的ID,没有中间环节,没有竞态条件。

其次,它极大地简化了应用层的代码逻辑。开发者不需要编写额外的查询语句,也不需要担心如何精确地匹配到刚刚插入的那条记录。一个简单的

INSERT ... RETURNING id
就能搞定,这让代码变得更简洁、更易读、更不容易出错。

最后,是性能上的优势。将

INSERT
SELECT
合并为一个数据库往返(round trip),意味着客户端和数据库服务器之间的通信开销减少了一半。在网络延迟较高或者需要频繁插入数据的场景下,这种优化是显而易见的。它避免了不必要的网络I/O和数据库资源消耗,使得整个操作更加高效。

如果主键不是
SERIAL
类型,
RETURNING
还能用吗?

当然可以!

RETURNING
子句的强大之处在于它不绑定于任何特定的数据类型或主键生成策略。无论你的主键是
SERIAL
BIGSERIAL
UUID
、或者是通过触发器(trigger)生成的,甚至是用户手动指定的值,只要它是你
INSERT
操作后数据表里真实存在的列,你都可以通过
RETURNING
来获取。

举个例子,如果你的主键是一个

UUID
类型,并且你是在应用层生成UUID然后插入的:

Draft&Goal-Detector
Draft&Goal-Detector

检测文本是由 AI 还是人类编写的

下载
CREATE TABLE products (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- 或者在应用层生成
    name VARCHAR(100) NOT NULL,
    price NUMERIC(10, 2)
);

假设你让数据库自动生成UUID:

INSERT INTO products (name, price) VALUES ('Laptop', 1200.00) RETURNING id;

或者,如果你在应用层生成了UUID:

-- 假设应用层生成了 'a1b2c3d4-e5f6-7890-1234-567890abcdef'
INSERT INTO products (id, name, price) VALUES ('a1b2c3d4-e5f6-7890-1234-567890abcdef', 'Monitor', 300.00) RETURNING id;

在这两种情况下,

RETURNING id
都会准确地返回那条新记录的
UUID
主键。

甚至,你不仅仅可以返回主键,任何你认为在

INSERT
后需要立即知道的列,都可以被
RETURNING
。比如,你可能想知道一个订单创建后,它的
order_id
created_at
时间戳:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT NOT NULL,
    order_date TIMESTAMP DEFAULT NOW()
);

INSERT INTO orders (customer_id) VALUES (101) RETURNING order_id, order_date;

这会返回新订单的ID和数据库自动生成的创建时间。这种灵活性使得

RETURNING
成为了PostgreSQL里处理插入操作后数据检索的“瑞士军刀”。

结合
ON CONFLICT
子句,
RETURNING
如何在 UPSERT 场景下发挥作用?

这里要提到一个PostgreSQL的杀手级特性——

INSERT ... ON CONFLICT
,也就是我们常说的UPSERT(更新或插入)。当这个特性与
RETURNING
结合时,它的实用性简直是指数级增长。

想象一个场景:你需要插入一条记录,但如果这条记录(根据某个唯一约束)已经存在,你就想更新它,并且无论最终是插入还是更新,你都希望获取到最终那条记录的ID和一些其他信息。这就是

INSERT ... ON CONFLICT ... DO UPDATE ... RETURNING
的用武之地。

我们继续用

users
表的例子,假设
email
字段是唯一的:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE
);

现在,我们想插入一个用户,如果

email
冲突了,就更新
username

-- 第一次插入,'john@example.com' 不存在
INSERT INTO users (username, email) VALUES ('John Doe', 'john@example.com')
ON CONFLICT (email) DO UPDATE SET username = EXCLUDED.username
RETURNING id, username, email;

-- 假设返回 id=1, username='John Doe', email='john@example.com'

-- 第二次插入,'john@example.com' 已经存在,会触发更新
INSERT INTO users (username, email) VALUES ('Johnny Bravo', 'john@example.com')
ON CONFLICT (email) DO UPDATE SET username = EXCLUDED.username
RETURNING id, username, email;

在第二次执行时,由于

email
冲突,
ON CONFLICT
子句会被激活,
username
会被更新为
Johnny Bravo
。此时,
RETURNING
子句会返回最终状态的记录信息。也就是说,它会返回
id=1
(因为是更新了原有记录),
username='Johnny Bravo'
email='john@example.com'

这个机制非常强大,它让你的应用程序可以以一种统一的方式处理“插入或更新并获取结果”的逻辑,无论是新增还是修改,你都能拿到最新、最准确的数据状态。这大大简化了业务逻辑层面的判断和处理,避免了多次查询和复杂的事务控制,让代码更健壮、更高效。在我看来,这是PostgreSQL在处理数据同步和数据一致性方面的一个非常优雅的解决方案。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

309

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

postgresql常用命令
postgresql常用命令

postgresql常用命令psql、createdb、dropdb、createuser、dropuser、l、c、dt、d table_name、du、i file_name、e和q等。本专题为大家提供postgresql相关的文章、下载、课程内容,供大家免费下载体验。

158

2023.10.10

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

978

2023.11.02

postgresql常用命令有哪些
postgresql常用命令有哪些

postgresql常用命令psql、createdb、dropdb、createuser、dropuser、l、c、dt、d table_name、du、i file_name、e和q等。更详细的postgresql常用命令,大家可以访问下面的文章。

199

2023.11.16

postgresql常用命令介绍
postgresql常用命令介绍

postgresql常用命令有l、d、d5、di、ds、dv、df、dn、db、dg、dp、c、pset、show search_path、ALTER TABLE、INSERT INTO、UPDATE、DELETE FROM、SELECT等。想了解更多postgresql的相关内容,可以阅读本专题下面的文章。

270

2023.11.20

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

358

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2082

2023.08.14

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

2

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
黑马云课堂jQuery基础视频教程
黑马云课堂jQuery基础视频教程

共46课时 | 10.1万人学习

10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号