it-swarm.com.de

Keine eindeutige oder Ausschlussbedingung, die mit ON CONFLICT übereinstimmt

Ich erhalte die folgende Fehlermeldung, wenn Sie folgende Einfügungstypen ausführen:

Abfrage:

INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 1) ON
CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET
updated_at = EXCLUDED.updated_at RETURNING *

Error:

SQL-Ausführung fehlgeschlagen (Grund: ERROR: Es gibt keine eindeutige oder ausschließende Einschränkung , Die der ON CONFLICT-Spezifikation entspricht.)

Ich habe auch einen einzigartigen INDEX:

CREATE UNIQUE INDEX uniq_person_accounts ON accounts USING btree (type,
person_id) WHERE ((type)::text = 'PersonAccount'::text);

Die Sache ist, dass es manchmal funktioniert, aber nicht jedes Mal. Ich zufällig bekomme Diese Ausnahme, was wirklich seltsam ist. Es scheint, dass es nicht auf den INDEX zugreifen kann oder es nicht weiß, dass es existiert.

Irgendein Vorschlag?

Ich verwende PostgreSQL 9.5.5.

Beispiel während der Ausführung des Codes, der versucht, ein Konto zu finden oder zu erstellen:

INSERT INTO accounts (type, person_id, created_at, updated_at) VALUES ('PersonAccount', 69559, '2017-02-03 12:09:27.259', '2017-02-03 12:09:27.259') ON CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET updated_at = EXCLUDED.updated_at RETURNING *
 SQL execution failed (Reason: ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification)

In diesem Fall bin ich mir sicher, dass das Konto nicht existiert. Außerdem gibt es niemals den Fehler aus, wenn die Person bereits ein Konto hat. Das Problem ist, dass es in einigen Fällen auch funktioniert, wenn noch kein Konto vorhanden ist. Die Abfrage ist genau gleich. 

11
Tiago Babo

Ich hatte keine Chance mit UPSERT zu spielen, aber ich denke, Sie haben einen Fall aus docs :

Beachten Sie, dass dies bedeutet, dass ein nicht-partieller eindeutiger Index (ein eindeutiger Index Ohne Prädikat) abgeleitet wird (und somit von ON CONFLICT verwendet wird) , Wenn ein solcher Index verfügbar ist, der alle anderen Kriterien erfüllt. Wenn ein Inferenzversuch nicht erfolgreich ist, wird ein Fehler ausgegeben.

1
Vao Tsun

Per die Dokumente ,

Alle table_name-eindeutigen Indizes, die ohne Rücksicht auf die Reihenfolge genau die -Konfliktziel-angegebenen Spalten/Ausdrücke enthalten, werden als Arbiter - Indizes abgeleitet (ausgewählt). Wenn ein index_predicate angegeben ist, muss es als weitere Anforderung Für die Inferenz Arbiter-Indizes erfüllen.

Die Dokumente sagen weiter:

[index_predicate are u] sed erlaubt den Rückschluss auf partielle eindeutige Indizes

Auf unauffällige Weise sagen die Dokumente, dass bei Verwendung eines partiellen Index und Mit ON CONFLICT das index_predicate angegeben werden muss . Es wird nicht für Sie abgeleitet. Ich habe dies hier gelernt, und das folgende Beispiel zeigt 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 erhalten wir eine Fehlermeldung:

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

Wenn Sie stattdessen jedoch das index_predicate angeben, 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 NICHTS wird geehrt.

0
unutbu