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:
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:
Flako
Dic 23, 2013 @ 16:23:06
Que tal buena tarde… me agrada mucho tu blog ya que por la red no he visto alguno especializado en firebird (a excepcion del de la pagina oficial) tengo una duda acerca de un procedure, soy nuevo en este tema y pues quisiera pedirte ayuda..
veras tengo mi procedure que ace una consulta pero necesito que me devuelva multiples filas, pero no me deja, lo que pretendo es que con el procedure que hago busque unos datos, para posteriormente pasarlos a otro procedure que me hara una operacion y al final me mostrara un unico resultado, hasta donde tengo entendido tengo que usar un ciclo..
el problema esta en que apenas inicio con la creacion de un procedure y ni hablar de un ciclo para ejecucion
de antemano gracias
wrov
Dic 23, 2013 @ 16:55:28
Que bueno que te agrade el blog.
En Firebird hay dos clases de stored procedures: ejecutables y seleccionables.
Lee ese artículo y si después tienes alguna duda me preguntas.
Saludos.
Walter.