Firebird nos da la posibilidad de usar SELECTs abreviados a los cuales se les llama “Cursores”. Son muy útiles cuando  los SELECTs son complejos y necesitamos utilizar varios de ellos en un stored procedure, trigger o execute block.

Funcionan de la siguiente manera:

  1. Se declara el cursor. Es allí donde se indica cual será el SELECT que le corresponde
  2. Se abre el cursor. A partir de ese momento ya podremos obtener las columnas que nos interesan
  3. Se extraen las filas del cursor. Se obtiene el valor de cada columna que declaramos en el SELECT, una fila por vez
  4. Se procesan las variables extraídas. Una vez que obtuvimos los valores de las columnas podemos utilizarlos como nos parezca
  5. Se cierra el cursor. Es la mejor práctica aunque si no lo hacemos el mismo Firebird lo cerrará cuando finalice el stored procedure, trigger o execute block donde se encuentra
CREATE PROCEDURE USANDO_CURSOR
   RETURNS(
      tnIdenti BIGINT,
      tcNombre VARCHAR(40))
AS
   DECLARE VARIABLE lcContinuar CHAR(1);
   DECLARE VARIABLE MiCursor CURSOR FOR (
      SELECT TAR_IDENTI, TAR_NOMBRE FROM TARJETAS);
BEGIN

   OPEN MiCursor;     /* Se abre el cursor */

   lcContinuar = 'S';

   WHILE (lcContinuar = 'S') DO BEGIN
      FETCH MiCursor INTO :tnIdenti, :tcNombre;     /* extrae una fila */
      IF (ROW_COUNT = 1) THEN BEGIN     /* si ROW_COUNT = 1 se leyó una fila */
         tcNombre = tcNombre || ' tarjeta procesada....';
         SUSPEND;
      END ELSE
         lcContinuar = 'N';     /* Si ROW_COUNT = 0 ya no hay más filas */
   END

   CLOSE MiCursor; /* Se cierra el cursor */

END;

¿Qué se hizo en este stored procedure?

Primero, se declaró un cursor de nombre “MiCursor” el cual corresponde a un SELECT de la tabla TARJETAS, de la cual nos interesan dos columnas: TAR_IDENTI y TAR_NOMBRE (Identificador de la tarjeta de crédito y Nombre de la tarjeta de crédito).

Segundo, se abrió el cursor de nombre “MiCursor” con el comando OPEN

Tercero, se escribió un ciclo WHILE el cual finalizará cuando la variable “lcContinuar” sea distinta de “S”

Cuarto, se extrajo una fila del SELECT que corresponde al cursor “MiCursor” con el comando FETCH

Quinto, se verificó si hay más filas para procesar o si ya se leyeron todas las filas. Cuando todas las filas han sido leídas el valor de la variable de contexto ROW_COUNT es siempre 0 (cero). Mientras haya filas por leer su valor es 1 (uno). Eso significa que podemos usar ROW_COUNT para saber cuando se leyeron todas las filas del SELECT, es el equivalente a la función EOF() que tienen algunos lenguajes de programación.

Sexto, si se pudo extraer una fila entonces se la procesó. Por supuesto que aquí podemos hacer lo que se nos ocurra con las variables obtenidas mediante el FETCH.

Séptimo, se regresó al inicio del WHILE para comprobar si debe repetirse el ciclo una vez más.

Octavo, se cerró el cursor.

Conclusión:

Los cursores son muy útiles sobre todo cuando no podemos tener todas las columnas que necesitamos en un solo SELECT. Si podemos tener a todas las columnas en un solo SELECT puede ser más práctico usar el comando SELECT … INTO

Como el Firebird nos permite tener abiertos dos, tres, o más cursores al mismo tiempo entonces podemos extraer de cada uno de ellos las columnas que necesitamos para procesarlas.

Muchas veces, en lugar de estar escribiendo un SELECT complicado, lleno de JOINs o de UNIONs es mucho más fácil, rápido y sencillo, usar varios cursores, se nos simplifica la vida de esta manera.

Los cursores son una gran facilidad que el Firebird nos provee, hay que utilizarlos para que nuestro código fuente sea más legible.

Anuncios