SQL Upsert语句不适用于非索引列

时间:2018-09-05 12:37:43

标签: sql postgresql

我正在使用PostgreSQL v9.6.6。我正在运行以下SQL:

insert into t_vs_config_key (name, description, is_brand_dependent)
  values ('ucp.cluster','UCP Cluster', true)
  ON CONFLICT (name) DO UPDATE SET is_brand_dependent=true;

这将导致以下错误,因为name列未编入唯一索引。我无法添加索引,因为现有数据不是唯一的。

  

错误:没有与ON匹配的唯一或排除约束   CONFLICT规范

问题 有没有想法如何在没有索引的情况下执行upsert语句?

谢谢

1 个答案:

答案 0 :(得分:0)

正如注释中已经提到的那样,没有唯一索引就不能使用ON CONFLICT

但是,您可以通过向表中添加新列以指示行是否有效并基于该标志创建部分唯一索引来确保将来的插入是唯一的:

alter t_vs_config_key 
  add column valid boolean not null default false;

这会将所有现有行初始化为valid = false

现在,以后再行时,将此列的默认值更改为true

alter table t_vs_config_key
    alter column valid set default true;

并通过添加检查约束确保不再有“无效”行可以插入:

alter table t_vs_config_key  
  add constraint check_valid check (valid);

现在您可以创建一个唯一索引:

create unique index on t_vs_config_key(name)
where valid;

可用于on conflict子句:

insert into t_vs_config_key (name, description, is_brand_dependent)
values ('ucp.cluster','UCP Cluster', true)
ON CONFLICT (name) where valid DO UPDATE 
  SET is_brand_dependent = true;

请注意语句中的where valid子句。