sql >> Base de Datos >  >> RDS >> PostgreSQL

Ninguna restricción única o de exclusión que coincida con ON CONFLICT

Según los documentos,

Todos los índices únicos de table_name que, independientemente del orden, contienen exactamente las columnas/expresiones especificadas en conflicto_objetivo se infieren (se eligen) como índices de árbitro. Si se especifica un predicado_índice, debe, como requisito adicional para la inferencia, satisfacer los índices del árbitro.

Los documentos continúan diciendo,

[index_predicate are u]sed para permitir la inferencia de índices únicos parciales

De una manera discreta, los documentos dicen que cuando se usa un índice parcial y se actualiza con ON CONFLICT, se debe especificar el predicado_índice . No se infiere para usted. Aprendí esto aquí, y el siguiente ejemplo lo demuestra.

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 tengamos:

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

Sin index_predicate obtenemos un error:

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

Pero si en su lugar incluye el predicado_índice, 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;

entonces no hay error y se respeta NO HACER NADA.