Error de PostgreSQL: more than one row returned by a subquery
ERROR: more than one row returned by a subquery used as an expression
Una subconsulta usada donde corresponde un único valor — tras =, en una lista SELECT, en una asignación — devolvió más de una fila. La mitad de las veces la consulta está mal (querías un conjunto, no un valor); la otra mitad la consulta está bien y los datos tienen duplicados que nadie conocía.
Qué significa este error
Un contexto de subconsulta escalar (WHERE x = (SELECT ...), SELECT (SELECT ...) AS y, SET col = (SELECT ...)) requiere cero filas (→ NULL) o una fila. Dos o más es un error en tiempo de ejecución — lo que significa que puede acechar en producción durante meses y dispararse el primer día en que los datos hacen que la subconsulta devuelva varias filas.
Causas comunes
- Querías un conjunto: la lectura natural era "cualquiera de estos" — eso es
IN, no=. - Correlación o filtro faltante: la subconsulta debería haber estado atada a la fila externa (
WHERE sub.user_id = outer.id) y no lo estaba. - Duplicados inesperados en datos que se asumían únicos — la subconsulta estaba bien, el invariante se rompió.
Cómo diagnosticarlo
-- Ejecuta la subconsulta por sí sola: ¿cuántas filas? ¿cuáles?
SELECT id FROM payments WHERE order_id = 42;
-- Si "no debería haber duplicados", encuéntralos:
SELECT order_id, count(*)
FROM payments
GROUP BY order_id
HAVING count(*) > 1;
Cómo solucionarlo
- Conjunto intencionado →
WHERE x IN (SELECT ...), oEXISTSpara comprobaciones de existencia puras. - Una fila específica intencionada → haz la elección explícita:
(SELECT ... ORDER BY created_at DESC LIMIT 1). Un LIMIT 1 pelado sin ORDER BY oculta el bug en vez de arreglarlo. - Invariante roto → limpia los duplicados, luego añade la restricción unique que hace la asunción exigible, para que esta clase de error no pueda volver.
🔍
La restricción que mantiene esto arreglado: duplicate key value violates unique constraint.
