Postgresql EXCLUDE 约束在 INSERT 时未触发 ON CONFLICT

Posted

技术标签:

【中文标题】Postgresql EXCLUDE 约束在 INSERT 时未触发 ON CONFLICT【英文标题】:Postgresql EXCLUDE constraint not triggering ON CONFLICT when INSERT 【发布时间】:2019-04-16 18:13:15 【问题描述】:

我已经定义了这个表:

CREATE TABLE market.price_history (
    item_id bigint NOT NULL,
    valid_time tstzrange DEFAULT tstzrange(now(), 'infinity'),
    sale_price money NOT NULL,
    promo_code bool NOT NULL DEFAULT false,
    EXCLUDE USING gist(item_id WITH =, valid_time WITH &&),
    EXCLUDE USING gist(item_id WITH =, sale_price WITH =, valid_time WITH &&)
);

但是当我执行这个 SQL 时:

WITH new_row_valid_time as(
    SELECT tstzrange(MAX(upper(valid_time)), 
                     'infinity'::timestamptz) as adjacent_valid_time 
    FROM market.price_history 
    WHERE item_id = 11
)
INSERT INTO market.price_history as ph
(item_id, valid_time, sale_price, promo_code)
VALUES(11,                        -- same id as existent row
       (SELECT adjacent_valid_time 
        FROM new_row_valid_time), -- adjacent range for existent row
       11.83,                     -- same price as the existent row
       False)
ON CONFLICT (item_id, sale_price, valid_time) DO
UPDATE SET valid_time = tstzrange(lower(ph.valid_time), 'infinity'::timestamptz)
WHERE ph.item_id = excluded.item_id
    AND ph.sale_price = excluded.sale_price
    AND upper(ph.valid_time) = lower(excluded.valid_time);

我期望执行ON CONFLICT 子句,因为要插入一些具有相同item_idsale_price 和与现有行相邻的valid_time 的行。相反,我得到了这个:

ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification

我是不是误会了什么?我相信第二个EXCLUDE 子句中的排除约束涉及相同的 3 列。我正在搜索文档,但 ON CONFLICT 的说明对我来说不是很清楚。

【问题讨论】:

【参考方案1】:

The documentation 有点简洁的评论:

请注意,不支持排除约束作为带有ON CONFLICT DO UPDATE 的仲裁器。

看源码让案例更清晰:

您永远不能对ON CONFLICT DO UPDATE 使用排除约束。

但是,您可以使用

ON CONFLICT ON CONSTRAINT price_history_item_id_valid_time_excl DO NOTHING

也就是说,您可以将命名排除约束与DO NOTHING 一起使用。

排除约束不存在“约束推断”,即,即使在DO NOTHING 的情况下,您也不能只在括号中指定索引表达式并让 PostgreSQL 找到相应的排除约束。

李>

【讨论】:

以上是关于Postgresql EXCLUDE 约束在 INSERT 时未触发 ON CONFLICT的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql:如何应用 pg_dump --exclude-table-data 补丁?

PostgreSQL 约束

PostgreSQL 约束

8.PostgreSQL约束

[TypeScript] Using Exclude and RootDir until File Globs Lands in 2.0.

postgresql字段值唯一约束