对于像这样的表:
CREATE TABLE Users(
id SERIAL PRIMARY KEY,
name TEXT UNIQUE
);
以下操作的正确单查询插入是什么:
给定一个用户name
,插入一条新记录并返回新的id
。但如果 name
已经存在,则返回 id
。
我知道 PostgreSQL 9.5 中用于 ON CONFLICT(column) DO UPDATE/NOTHING
的新语法,但我无法弄清楚它如何(如果有的话)提供帮助,因为我需要返回 id
。
看来 RETURNING id
和 ON CONFLICT
不属于一起。
最佳答案
UPSERT 实现非常复杂,以防止并发写访问。看看this Postgres Wiki在初始开发期间用作日志。 Postgres 黑客决定不在 Postgres 9.5 的第一个版本的 RETURNING
子句中包含“排除的”行。他们可能会为下一个版本构建一些东西。
这是手册中解释您的情况的关键语句:
The syntax of the
RETURNING
list is identical to that of the output list ofSELECT
. Only rows that were successfully inserted or updated will be returned. For example, if a row was locked but not updated because anON CONFLICT DO UPDATE ... WHERE
clause condition was not satisfied, the row will not be returned.
大胆强调我的。
对于要插入的单行:
同一张表上没有并发写入负载
WITH ins AS (
INSERT INTO users(name)
VALUES ('new_usr_name') -- input value
ON CONFLICT(name) DO NOTHING
RETURNING users.id
)
SELECT id FROM ins
UNION ALL
SELECT id FROM users -- 2nd SELECT never executed if INSERT successful
WHERE name = 'new_usr_name' -- input value a 2nd time
LIMIT 1;
可能在表上并发写入负载
改为考虑这个(对于单行 INSERT
):
要插入一组行:
所有这三个都有非常详细的解释。
关于sql - 从条件 INSERT 中获取 Id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36083669/