PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Nessun vincolo univoco o di esclusione corrispondente a ON CONFLICT

Secondo i documenti,

Tutti gli indici univoci table_name che, indipendentemente dall'ordine, contengono esattamente le colonne/espressioni specificate per il conflitto_destinazione vengono dedotte (scelte) come arbiterindex. Se viene specificato un index_predicate, deve, come ulteriore requisito per l'inferenza, soddisfare gli indici dell'arbitro.

I documenti continuano a dire,

[index_predicate sono utilizzati per consentire l'inferenza di indici univoci parziali

In modo discreto, i documenti dicono che quando si utilizza un indice parziale e si esegue l'upserting con ON CONFLICT, deve essere specificato index_predicate . Non è dedotto per te. L'ho imparato qui e l'esempio seguente lo dimostra.

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);

in modo da avere:

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

Senza index_predicate otteniamo un errore:

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

Ma se invece includi 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;

quindi non ci sono errori e NON FARE NULLA è onorato.