PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Nenhuma restrição exclusiva ou de exclusão correspondente ao ON CONFLICT


De acordo com os documentos,

Todos os índices exclusivos table_name que, sem levar em conta a ordem, contêm exatamente as colunas/expressões especificadas por conflict_target são inferidos (escolhidos) como índices de árbitro. Se um index_predicate for especificado, ele deverá, como requisito adicional para inferência, satisfazer os índices de árbitro.

Os documentos continuam dizendo,

[index_predicate são usados ​​para permitir a inferência de índices únicos parciais

De uma forma discreta, os documentos estão dizendo que ao usar um índice parcial e upserting com ON CONFLICT, o index_predicate deve ser especificado . Não é inferido para você. Eu aprendi isso aqui, e o exemplo a seguir demonstra isso.
CREATE TABLE test.accounts (
    id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    type text,
    person_id int);
CREATE UNIQUE INDEX accounts_note_idx on accounts (type, person_id) WHERE ((type)::text = 'PersonAccount'::text);
INSERT INTO  test.accounts (type, person_id) VALUES ('PersonAccount', 10);

para que tenhamos:
unutbu=# select * from test.accounts;
+----+---------------+-----------+
| id |     type      | person_id |
+----+---------------+-----------+
|  1 | PersonAccount |        10 |
+----+---------------+-----------+
(1 row)

Sem index_predicate obtemos um erro:
INSERT INTO  test.accounts (type, person_id) VALUES ('PersonAccount', 10) ON CONFLICT (type, person_id) DO NOTHING;
-- ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification

Mas se você incluir o index_predicate, WHERE ((type)::text = 'PersonAccount'::text) :
INSERT INTO  test.accounts (type, person_id) VALUES ('PersonAccount', 10)
ON CONFLICT (type, person_id)
WHERE ((type)::text = 'PersonAccount'::text) DO NOTHING;

então não há erro e DO NADA é honrado.