PostgreSQL-Fehler: no unique or exclusion constraint matching the ON CONFLICT specification

ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification

INSERT ... ON CONFLICT braucht einen Schiedsrichter: einen Unique- (oder Exclusion-) Constraint, der definiert, was "Konflikt" bedeutet. Das von Ihnen geschriebene Konfliktziel muss genau einem entsprechen — dieselbe Spaltenmenge, derselbe Ausdruck, dasselbe Partial-Prädikat. Keine Übereinstimmung, kein Upsert.

Was dieser Fehler bedeutet

PostgreSQL rät nicht, welchen Constraint Sie meinen. ON CONFLICT (email) erfordert einen Unique-Index auf genau (email):

Häufige Ursachen

So diagnostizieren Sie ihn

\d users   -- listet Indizes und Constraints mit ihrer genauen Definition

Vergleichen Sie das Konfliktziel im fehlschlagenden INSERT mit den Indexdefinitionen und prüfen Sie Spalten, Ausdrücke und WHERE-Klauseln buchstäblich.

So beheben Sie ihn

-- Der Constraint fehlt → erstellen Sie ihn (in Produktion: CONCURRENTLY)
CREATE UNIQUE INDEX CONCURRENTLY users_email_key ON users (email);

-- Ausdrucks-Index → das Ziel muss ihn wiederholen:
INSERT INTO users (email) VALUES ('[email protected]')
ON CONFLICT (lower(email)) DO NOTHING;

-- Partieller Index → das Ziel muss das Prädikat wiederholen:
INSERT INTO users (email) VALUES ('[email protected]')
ON CONFLICT (email) WHERE deleted_at IS NULL DO NOTHING;

Alternativ benennen Sie den Constraint direkt — ON CONFLICT ON CONSTRAINT users_email_key — obwohl die Spaltenform Umbenennungen des Constraints besser übersteht.

🔍 Der Fehler, den ON CONFLICT verhindern soll: duplicate key value violates unique constraint.
🔍 Weiterführend: Den richtigen Index wählen — Unique-, Partial- und Ausdrucksindizes.