PostgreSQL-Fehler: more than one row returned by a subquery
ERROR: more than one row returned by a subquery used as an expression
Eine Subquery, die dort verwendet wird, wo ein einzelner Wert hingehört — nach =, in einer SELECT-Liste, in einer Zuweisung — hat mehr als eine Zeile zurückgegeben. Die Hälfte der Zeit ist die Query falsch (Sie meinten eine Menge, keinen Wert); die andere Hälfte ist die Query richtig und die Daten haben Duplikate, von denen niemand wusste.
Was dieser Fehler bedeutet
Ein skalarer Subquery-Kontext (WHERE x = (SELECT ...), SELECT (SELECT ...) AS y, SET col = (SELECT ...)) erfordert null Zeilen (→ NULL) oder eine Zeile. Zwei oder mehr sind zur Ausführungszeit ein Fehler — was bedeutet, dass er monatelang in der Produktion lauern kann und am ersten Tag feuert, an dem die Daten die Subquery mehrzeilig machen.
Häufige Ursachen
- Sie meinten eine Menge: die natürliche Lesart war "irgendeine von diesen" — das ist
IN, nicht=. - Fehlende Korrelation oder fehlender Filter: die Subquery hätte an die äußere Zeile gebunden sein sollen (
WHERE sub.user_id = outer.id) und war es nicht. - Unerwartete Duplikate in Daten, die als eindeutig angenommen wurden — die Subquery war richtig, die Invariante brach.
So diagnostizieren Sie ihn
-- Führen Sie die Subquery allein aus: wie viele Zeilen? welche?
SELECT id FROM payments WHERE order_id = 42;
-- Wenn "es sollte keine Duplikate geben", finden Sie sie:
SELECT order_id, count(*)
FROM payments
GROUP BY order_id
HAVING count(*) > 1;
So beheben Sie ihn
- Menge beabsichtigt →
WHERE x IN (SELECT ...), oderEXISTSfür reine Existenzprüfungen. - Eine bestimmte Zeile beabsichtigt → machen Sie die Wahl explizit:
(SELECT ... ORDER BY created_at DESC LIMIT 1). Ein bloßes LIMIT 1 ohne ORDER BY versteckt den Bug, statt ihn zu beheben. - Gebrochene Invariante → bereinigen Sie die Duplikate, fügen Sie dann den Unique-Constraint hinzu, der die Annahme durchsetzbar macht, sodass diese Fehlerklasse nicht zurückkehren kann.
🔍
Der Constraint, der dies dauerhaft behebt: duplicate key value violates unique constraint.
