PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Keine Eindeutigkeits- oder Ausschlussbeschränkung, die mit ON CONFLICT übereinstimmt

Gemäß der Dokumentation

Alle eindeutigen Tabellennamen-Indizes, die unabhängig von der Reihenfolge genau die durch Konflikt_Ziel angegebenen Spalten/Ausdrücke enthalten, werden als Arbiter-Indizes abgeleitet (ausgewählt). Wenn ein index_predicate angegeben ist, muss es als weitere Voraussetzung für die Inferenz Arbiter-Indizes erfüllen.

Die Dokumente sagen weiter:

[index_predicate werden verwendet, um Rückschlüsse auf teilweise eindeutige Indizes zu ermöglichen

Untertrieben sagen die Dokumente, dass bei der Verwendung eines partiellen Indexes und beim Upserting mit ON CONFLICT das index_predicate angegeben werden muss . Es wird für Sie nicht abgeleitet. Ich habe das hier gelernt, und das folgende Beispiel demonstriert dies.

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

so dass wir haben:

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

Ohne index_predicate wir bekommen einen Fehler:

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

Aber wenn Sie stattdessen das index_predicate einfügen, 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;

dann gibt es keinen Fehler und DO NOTHING wird berücksichtigt.