A veces en nuestras consultas necesitamos mostrar columnas cuyos contenidos provienen de otras tablas y además lo hacen en forma condicional.

Ejemplo:

En una tabla MOVIMCAB tenemos una columna llamada MVC_TIPMOV la cual nos indica el tipo de movimiento (‘ECM’ es una entrada por compras, ‘SVT’ es una salida por ventas, etc.) y donde también guardamos el Identificador del Proveedor (cuando se trata de una compra) o el Identificador del Cliente (cuando se trata de una venta).

Ahora, necesitamos una consulta que nos muestre el nombre del Proveedor o el nombre del Cliente, según corresponda. Para ello haremos uso de la construcción CASE … WHEN … END

SELECT
   MVC_FECHAX,
   MVC_NRODOC,
   MVC_TIPMOV,
   CASE
      WHEN MVC_TIPMOV = 'ECM' THEN (SELECT PRO_NOMBRE FROM PROVEEDORES WHERE PRO_IDENTI = MVC_IDEPRO)
      WHEN MVC_TIPMOV = 'SVT' THEN (SELECT CLI_NOMBRE FROM CLIENTES    WHERE CLI_IDENTI = MVC_IDECLI)
   END AS NOMBRE
FROM
   MOVIMCAB
WHERE
   MVC_TIPMOV IN ('ECM', 'SVT')

Y este es el resultado (parcial, por supuesto) que obtuvimos:

CONDICIONAL1

Captura 1. Si haces clic en la imagen la verás más grande

Como puedes ver, en la columna NOMBRE tenemos el nombre de un Proveedor (cuando se trata de una compra) o el nombre de un Cliente (cuando se trata de una venta). Y para saber de cual de ellos se trata podemos mirar el contenido de la columna MVC_TIPMOV.

ERROR: Multiple rows in singleton select

Si ves ese mensaje de error significa que el SELECT interno devolvió más de una fila pero debería haber devuelto solamente una fila (o ninguna, pero jamás más de una).

¿Cuál es el problema?

Que si el SELECT devuelve varias filas el Firebird no puede saber cual de esas filas es la correcta. Por ejemplo, si el SELECT devuelve el nombre de 500 clientes ¿cuál de esos 500 nombres es el que debe mostrar? imposible que el Firebird pueda saberlo y por lo tanto te muestra un mensaje de error.

Para evitar el error siempre tienes que asegurarte que la condición que pusiste en la cláusula WHERE limite el resultado a una sola fila.

En el ejemplo de arriba se usó el Identificador del Proveedor o del Cliente. Como esos identificadores son únicos y jamás pueden repetirse entonces estamos seguros de que jamás obtendremos el error «multiple rows in singleton select». Sin embargo cuando no usas identificadores ni claves primarias ni claves únicas la posibilidad de encontrar ese error siempre existirá.

Artículo relacionado:

El índice del blog Firebird21