Zgodnie z dokumentacją,
Wszystkie unikatowe indeksy nazwa_tabeli, które, bez względu na kolejność, zawierają dokładnie kolumny/wyrażenia określone przez conflict_target, są wywnioskowane (wybrane) jako indeksy arbitralne. Jeśli określono predykat index_predicate, musi on, jako dalsze wymaganie dla wnioskowania, spełniać indeksy arbitrów.
Dokumenty mówią dalej:
[index_predicate są] używane, aby umożliwić wnioskowanie o częściowych unikalnych indeksach
W sposób zaniżony, dokumentacja mówi, że podczas korzystania z indeksu częściowego i zamieniania z ON CONFLICT należy określić predykat_indeksu . To nie jest dla ciebie wywnioskowane. Dowiedziałem się tego tutaj, a poniższy przykład to pokazuje.
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);
tak, że mamy:
unutbu=# select * from test.accounts;
+----+---------------+-----------+
| id | type | person_id |
+----+---------------+-----------+
| 1 | PersonAccount | 10 |
+----+---------------+-----------+
(1 row)
Bez index_predicate
otrzymujemy błąd:
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
Ale jeśli zamiast tego dołączysz 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;
wtedy nie ma błędu i NIC NIE jest honorowane.