【问题标题】:PostgreSQL Partial Indexes and UPSERTPostgreSQL 部分索引和 UPSERT
【发布时间】:2017-06-30 10:35:09
【问题描述】:

在谷歌上搜索了很多之后,我的问题描述如下:

CREATE TABLE security (
  id          SERIAL PRIMARY KEY,
  vendor      VARCHAR(20),
  external_id VARCHAR(20),
  extinct     BOOLEAN DEFAULT FALSE
);

CREATE UNIQUE INDEX unique_vendor ON security(vendor, extinct) where vendor is not null;
CREATE UNIQUE INDEX unique_external_id ON security(external_id, extinct) where external_id is not null;

尝试插入值:

insert into security (vendor, external_id, extinct) 
  values('Legion', 'LGNONE', false)
  ON CONFLICT(vendor, external_id, extinct) DO UPDATE
  SET vendor = 'Legion', external_id = 'LGNONE', extinct = false;

结果:

[42P10] ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification

尽管如此(根据规范):

insert into security (vendor, external_id, extinct) 
    values('Legion', 'LGNONE', false)
    ON CONFLICT DO NOTHING;

PostgreSQL documentation stands that it should work

PostgreSQL v9.5

我的目标是想办法在这个表的多个可空列上创建唯一索引,并在 UPSERT 上用新行更新旧行

【问题讨论】:

    标签: sql postgresql indexing unique upsert


    【解决方案1】:

    on conflict 中使用的conflict_target 必须标识现有的唯一索引。你不能使用

    on conflict (vendor, external_id, extinct)
    

    因为您在三列上没有索引。 Postgres 不是很聪明地结合多个索引来满足你的冲突目标。

    但是,您可以像这样创建一个部分索引:

    create unique index unique_vendor_external_id 
        on security(vendor, external_id, extinct) 
        where coalesce(vendor, external_id) is not null;
    

    现在您可以将三列用作冲突目标:

    insert into security (vendor, external_id, extinct) 
        values('Legion', 'LGNONE', false)
    on conflict (vendor, external_id, extinct)          -- exact match to the index definition 
        where coalesce(vendor, external_id) is not null -- obligatory index_predicate
    do update set
        vendor = excluded.vendor,
        external_id = excluded.external_id,
        extinct = excluded.extinct
    

    注意特殊记录excluded的使用。对于文档:

    ON CONFLICT DO UPDATE 中的 SET 和 WHERE 子句可以使用表的名称(或别名)访问现有行,并使用特殊的 excluded 表访问建议插入的行。 p>

    【讨论】:

    • 这是绝妙的建议和答案!非常感谢!
    • 在找到这个答案之前,我已经在谷歌上搜索了 3 个小时,但没有运气。真的很感谢这个答案对我帮助很大。
    • (where + 约束) 是使用带约束的唯一索引时的键。真的很丑,但是很管用。
    猜你喜欢
    • 2018-03-25
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 2018-11-03
    • 2021-12-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多