具有多列唯一约束名称的 PostgreSQL ON CONFLICT

PostgreSQL ON CONFLICT with multi-column unique constraint name

当我尝试使用 PostgreSQL 进行 UPSERT 时,我 运行 陷入了一种我无法理解的行为。文档似乎表明 INSERT 语句的 冲突目标 可以是索引表达式 约束名称。但是,在尝试引用约束名称时,出现 "column ... does not exist" 错误。

我的第一次尝试是创建一个 UNIQUE 索引,它与约束推断一起工作得很好:

create table kv (key text, value text, extra text);
create unique index kv_key_value on kv(key, value);
insert into kv (key, value) values ('k1', 'v1');
-- this works:
insert into kv (key, value, extra) values ('k1', 'v1', 'e1')
  on conflict (key, value) do update set extra=excluded.extra;

-- this does not
insert into kv (key, value, extra) values ('k1', 'v1', 'e1')
  on conflict (kv_key_value) do update set extra=excluded.extra;

描述以上 table,我在 "Indexes:"

下看到以下内容
"kv_key_value" UNIQUE, btree (key, value)

我的第二次尝试是将唯一约束明确地放在创建 table:

create table kv (
  key text,
  value text,
  extra text,
  constraint kv_key_value unique(key, value));

描述上述 table,"Indexes:" 的输出略有不同("UNIQUE CONSTRAINT" 与前面示例中的 "UNIQUE"):

"kv_key_value" UNIQUE CONSTRAINT, btree (key, value)

但是我仍然无法将约束名称指定为冲突目标:

insert into kv (key, value, extra) values ('k1', 'v1', 'e1')
  on conflict (kv_key_value) do update set extra=excluded.extra;
ERROR:  column "kv_key_value" does not exist
LINE 2:       on conflict (kv_key_value) do update set extra=exclude...

我是不是误会了什么?我完全明白我可以使用等效表达式并依赖约束推理,但我想知道为什么约束名称在文档听起来应该如此时似乎不起作用?

你的语法有误。

对于约束,应该是:

INSERT INTO kv (key, value, extra)
   VALUES ('k1', 'v1', 'e1')
   ON CONFLICT ON CONSTRAINT kv_key_value
      DO UPDATE SET extra = excluded.extra;