对于这样的表:
CREATE TABLE Users( id SERIAL PRIMARY KEY, name TEXT UNIQUE );
什么是正确的一次查询插入以下操作:
给定用户name,插入新记录并返回新记录id。但是,如果name已经存在,则只需返回id。
name
id
我知道PostgreSQL 9.5中针对的新语法ON CONFLICT(column) DO UPDATE/NOTHING,但是鉴于我需要id返回,因此我无法弄清楚它是否有帮助(如果有的话)。
ON CONFLICT(column) DO UPDATE/NOTHING
似乎RETURNING id和ON CONFLICT不属于在一起。
RETURNING id
ON CONFLICT
UPSERT的实现非常复杂,以确保不会发生并发写访问。看一下这个Postgres Wiki,它在最初的开发过程中用作日志。Postgres黑客决定RETURNING在Postgres 9.5的第一个发行版的子句中不包括“排除”行。他们可能会为下一个版本构建一些内容。
RETURNING
这是手册中解释您的情况的重要说明:
该RETURNING列表的语法与的输出列表的语法相同SELECT。 仅返回成功插入或更新的行。 例如,如果某行被锁定但由于ON CONFLICT DO UPDATE ... WHERE不满足子句条件而未更新,则不会返回该行。
SELECT
ON CONFLICT DO UPDATE ... WHERE
大胆强调我的。
对于要插入的 单行 :
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)
INSERT
要插入一 组行 :
所有这三个都有非常详细的说明。