Ограничение Postgresql EXCLUDE не вызывает ON CONFLICT при вставке - PullRequest
2 голосов
/ 16 апреля 2019

Я определил эту таблицу:

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_id, sale_price и valid_time, смежные с существующей.Вместо этого я получаю это:

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

Я что-то не так понимаю?Я считаю, что ограничение исключения во втором предложении EXCLUDE включает те же 3 столбца.Я ищу документы, но инструкции ON CONFLICT мне не совсем понятны.

1 Ответ

2 голосов
/ 16 апреля 2019

Документация Несколько кратких замечаний:

Обратите внимание, что ограничения исключения не поддерживаются в качестве арбитров с ON CONFLICT DO UPDATE.

Просмотр исходного кода проясняет ситуацию:

  • Вы никогда не можете использовать исключающее ограничение с ON CONFLICT DO UPDATE.

  • Однако вы можете использовать

    ON CONFLICT ON CONSTRAINT price_history_item_id_valid_time_excl DO NOTHING
    

    То есть вы можете использовать именованное исключающее ограничение с DO NOTHING.

  • Нет & ldquo; логического вывода ограничения & rdquo; с ограничениями исключения, т. е. даже в случае DO NOTHING вы не можете просто указать индексированные выражения в скобках и заставить PostgreSQL найти соответствующее ограничение исключения.

...