【问题标题】:SQL Upsert statement not working on non indexed columnSQL Upsert 语句不适用于非索引列
【发布时间】:2018-09-05 12:37:43
【问题描述】:

我正在使用 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 匹配的唯一或排除约束 冲突规范

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

谢谢

【问题讨论】:

  • AFAIK 没有唯一索引就无法做到
  • 如果你使用ON CONFLICT (name, description, is_brand_dependent) ?
  • @AnonyDev 如果我尝试ON CONFLICT (name, description, is_brand_dependent)会得到同样的错误@
  • 也许在这里回复但不确定:medium.com/@betakuang/…
  • 因为如果您没有唯一索引/主键,则不会发生冲突。数据库的冲突是当它不可能做某事时(例如将非唯一值放入唯一索引)。

标签: sql postgresql


【解决方案1】:

正如 cmets 中已经提到的,您不能使用没有唯一索引的 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 子句。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 2015-10-07
    • 1970-01-01
    • 2021-01-27
    • 2021-08-30
    • 2019-05-18
    相关资源
    最近更新 更多