Entendiendo a los FOR SELECT

2 comentarios

Si dentro de un stored procedure o de un trigger quieres conocer cuales son los valores que tienen las columnas de una tabla entonces tienes dos formas:

  • Asignación directa
  • Usando un FOR SELECT

La asignación directa es la más conveniente cuando solamente te interesa el valor de una columna, por ejemplo:

lnMiVariable = (SELECT MiColumna FROM MiTabla WHERE MiCondición);

Para que funcione, la asignación directa debe cumplir dos requisitos:

  1. Que el SELECT devuelva una sola columna de una sola fila.
  2. Que el SELECT esté rodeado por paréntesis

Pero si necesitas varias columnas o varias filas entonces la asignación directa no es la mejor alternativa. Podrías usarla y funcionará, pero puede ser excesivamente lenta si las columnas son varias y las filas son muchas (además de que escribirás un montón). Para estos casos existe una mucha mejor alternativa: usar el FOR SELECT.

¿Qué hace el FOR SELECT?

Es muy similar a un SELECT pero siempre y en todos los casos el contenido de las columnas es asignado a variables de memoria. ¿Por qué eso? porque dentro de un stored procedure o de un trigger no se puede directamente usar una columna de una tabla. Entonces, si necesitamos usarla debemos previamente guardarla en una variable de memoria.

Columna —> Variable_de_memoria

Escribiendo un FOR SELECT

La forma general de escribir un FOR SELECT es la siguiente:

FOR SELECT
   MiColumna1,
   MiColumna2,
   MiColumna3
FROM
   MiTabla
INTO
   :MiVariable1,
   :MiVariable2,
   :MiVariable3
DO BEGIN
   -- Aquí se pueden usar las variables
END
-- Aquí también se pueden usar las variables

 Desde luego que en el SELECT puedes usar las cláusulas WHERE, GROUP BY, HAVING, etc.

Lo que se obtiene al ejecutar un FOR SELECT son variables que tienen el mismo valor que las columnas de la tabla. Así, dentro de MiVariable1 tendremos el valor de MiColumna1, dentro de MiVariable2 tendremos el valor de MiColumna2, etc.

Habrás notado que después de la cláusula INTO se ponen los nombres de las variables prefijados con el símbolo :

¿Por qué eso?

Porque es la forma que tiene el Firebird para saber si te estás refiriendo a una columna de una tabla o a una variable de memoria. En todos los lugares donde puede existir confusión es obligatorio que a las variables de memoria se las prefije con los dos puntos. De esa forma el Firebird podrá saber si quieres usar una columna o una variable de memoria.

Conclusión:

Cuando dentro de un stored procedure o de un trigger necesitamos obtener los valores que tienen las columnas de una tabla podemos hacerlo de dos formas:

  1. Con asignación directa
  2. Escribiendo un FOR SELECT

La asignación directa es la más conveniente cuando solamente nos interesa una columna aislada. Cuando estamos interesados en varias columnas entonces lo más conveniente es usar un FOR SELECT.

Todos los FOR SELECT deben tener una cláusula INTO y a continuación de la cláusula INTO debemos escribir los nombres de las variables de memoria prefijadas con dos puntos.

Se las prefija con dos puntos para que el Firebird pueda saber si nos estamos refiriendo a una columna de una tabla o a una variable de memoria. De esa manera las distingue.

Prefijar a una variable de memoria con los dos puntos solamente es necesario en los lugares donde el Firebird se puede confundir. En los lugares donde no hay confusión posible no es necesario (aunque si las prefijamos, ningún problema).

Artículos relacionados:

Entendiendo a los stored procedures

Entendiendo a los triggers

Teniendo FOR SELECT anidados

El índice del blog Firebird21

 

Teniendo FOR SELECT anidados

Deja un comentario

En ocasiones necesitamos tener FOR SELECT anidados. ¿Es eso posible en Firebird?

Sí, ningún problema.

Aquí vemos un ejemplo, este stored procedure no hace algo útil, sirve solamente para mostrar que se pueden anidar los FOR SELECT si los necesitamos anidados.

CREATE PROCEDURE FOR_ANIDADOS
   RETURNS(
      ftnIdenti TYPE OF COLUMN MOVIMCAB.MVC_IDENTI,
      ftnCantid TYPE OF COLUMN MOVIMDET.MOV_CANTID)
AS
   DECLARE VARIABLE lnIdeCab TYPE OF COLUMN MOVIMCAB.MVC_IDENTI;
   DECLARE VARIABLE ldFechax TYPE OF COLUMN MOVIMCAB.MVC_FECHAX;
   DECLARE VARIABLE lcNroDoc TYPE OF COLUMN MOVIMCAB.MVC_NRODOC;
   DECLARE VARIABLE lnIdePrd TYPE OF COLUMN MOVIMDET.MOV_IDENTI;
   DECLARE VARIABLE lnCantid TYPE OF COLUMN MOVIMDET.MOV_CANTID;
BEGIN

   FOR SELECT
      MVC_IDENTI,
      MVC_FECHAX,
      MVC_NRODOC
   FROM
      MOVIMCAB
   INTO
      :lnIdeCab,
      :ldFechax,
      :lcNroDoc
   DO BEGIN
      FOR SELECT
         MOV_IDEPRD,
         MOV_CANTID
      FROM
         MOVIMDET
      WHERE
         MOV_IDECAB = :lnIdeCab
      INTO
         :lnIdePrd,
         :lnCantid
      DO BEGIN
         ftnIdenti = :lnIdeCab;
         ftnCantid = :lnCantid;
         SUSPEND;
      END
   END

END;

Como puedes ver, ningún secreto, aunque por supuesto debes verificar que se cumplan las condiciones del WHERE para que el FOR SELECT arroje algunos resultados. También recuerda que debes incluir el comando SUSPEND en el lugar donde quieres que el stored procedure te devuelva valores. Los valores que devolverá serán los que tienen los parámetros de salida (es decir, los que se encuentran después del RETURNS) en el momento de ejecutarse el SUSPEND.

El autor de este blog utiliza la notación camello y siempre los parámetros de salida empiezan con la letra “f”, significando “Firebird”.

De esa manera es muy fácil saber si una variable es una variable local (porque empieza con “l”), un parámetro de entrada (porque empieza con “t”) o un parámetro de salida (porque empieza con “f”).

 Artículo relacionado:

La notación camello

El índice del blog Firebird 21