PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Aucune contrainte d'unicité ou d'exclusion correspondant à ON CONFLICT

Selon la documentation,

Tous les index uniques table_name qui, quel que soit l'ordre, contiennent exactement les colonnes/expressions spécifiées par conflict_target sont déduits (choisis) en tant qu'index arbitres. Si un index_predicate est spécifié, il doit, comme exigence supplémentaire pour l'inférence, satisfaire les index arbitres.

Les docs poursuivent en disant :

[index_predicate]est utilisé pour permettre l'inférence d'index uniques partiels

D'une manière discrète, les docs disent que lors de l'utilisation d'un index partiel et de la mise à jour avec ON CONFLICT, l'index_predicate doit être spécifié . Ce n'est pas inféré pour vous. J'ai appris ceci ici, et l'exemple suivant le démontre.

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

de sorte que nous avons :

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

Sans index_predicate nous obtenons une erreur :

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

Mais si à la place vous incluez le 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;

alors il n'y a pas d'erreur et NE RIEN est honoré.