Firebird no tiene una seudo-columna que nos permita conocer el número de la fila de una tabla porque la Teoría de Bases de Datos Relacionales nos enseña que a las filas las debemos identificar por sus valores, no por sus posiciones dentro de la tabla.

Sin embargo, a veces podríamos necesitar que las filas retornadas por un SELECT estén numeradas, o sea, que la primera fila tenga una columna con el valor 1, la segunda fila una columna con el valor 2, la tercera fila una columna con el valor 3 y así sucesivamente. Hay varios métodos que podemos utilizar para conseguir ese objetivo.

Método Nº 1. Usando un generador

Numerando1(haciendo click en la imagen la verás más grande)

Aquí, creamos un generador y luego mediante la función GEN_ID() le asignamos sus valores. Al final debemos eliminar al generador porque si no lo hacemos la siguiente vez que intentemos crearlo tendremos un error, porque el generador ya existe. Alternativamente, podríamos inicializar el valor a 0 (cero) antes del siguiente SELECT escribiendo: SET GENERATOR GEN_PRUEBA1 TO 0;

El defecto de este método es que no puede ser usado en un stored procedure ni en un trigger ni en un execute block porque en ellos no podemos crear ni eliminar generadores.

Método Nº 2. Referenciando una tabla con sí misma

SELECT
   COUNT(*) AS FilaNro,
   M.MAR_IDENTI,
   M.MAR_NOMBRE
FROM
   MARCAS M
JOIN
   MARCAS N
      ON M.MAR_IDENTI = N.MAR_IDENTI
GROUP BY
   M.MAR_IDENTI,
   M.MAR_NOMBRE

Aquí, la tabla MARCAS se junta con … la tabla MARCAS. Este método funciona siempre pero es lento, no deberías usarlo si la cantidad de filas devueltas por el SELECT es grande (cuanto es “grande” depende de la velocidad de tu hardware).

Método Nº 3. Usando una variable de contexto del usuario

En este método se usa una muy buena característica del Firebird: las variables de contexto del usuario.

¿Qué son las variables de contexto del usuario?

Son variables cuyo nombre y valor los elegimos nosotros, los desarrolladores, los programadores. Por lo tanto, esas variables pueden tener cualquier nombre y cualquier valor que deseemos.

Puedes leer más sobre las variables de contexto de los usuarios en los dos artículos de abajo.

SELECT
   RDB$GET_CONTEXT('USER_TRANSACTION', 'MiVar') as nNumeroFila,
   P.PRD_NOMBRE,
   RDB$SET_CONTEXT('USER_TRANSACTION', 'MiVar', COALESCE(CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'MiVar') AS INTEGER), 0) + 1)
FROM
   PRODUCTOS P
ORDER BY
   P.PRD_NOMBRE

Como el Firebird recorre los SELECT de derecha a izquierda entonces podemos aprovecharnos de eso para crear las variables que necesitamos y usarlas en ese mismo SELECT.

Aquí, con la función RDB$SET_CONTEXT() creamos una variable propia llamada MiVar o le asignamos un valor a esa variable (con la función RDB$SET_CONTEXT podemos hacer ambas cosas). La función COALESCE() devuelve el valor de MiVar si existe o el número 0 (cero) si no existe. Cualquiera sea el caso se le suma 1 a la variable MiVar. Ese valor que ahora tiene MiVar (uno si no existía o el valor anterior más uno si ya existía) es el que se muestra en la primera columna del SELECT.

El defecto de este método es que te resultará difícil recordarlo y deberás buscarlo en este blog o dentro de alguna Base de Datos cuando quieras usarlo.

Método Nº 4. Usando una columna para guardar el número de la fila

Con este método lo que haces es:

  1. Agregarle una columna a tu tabla, por ejemplo: PRD_NUMREG para guardar en esa columna el número de registro (de fila)
  2. Crear un generador, por ejemplo: GEN_NUMREG
  3. Asignarle valores a la columna agregada:
UPDATE
   PRODUCTOS
SET
   PRD_NUMREG = GEN_ID(GEN_NUMREG, 1)

Este método te servirá para simular el número de registro que se utiliza en las tablas .DBF y que puedes obtener con la función RECNO() de los lenguajes que usan tablas .DBF

Además, si necesitas conocer la cantidad total de filas de la tabla puedes obtener esa información muy fácilmente con un SELECT como el siguiente:

SELECT
   MAX(P.PRD_NUMREG) AS CantidadFilas
FROM
   PRODUCTOS P

El defecto de este método es que cada SELECT no empezará con 1, sino con el número que tenga asignada esa fila. A veces, eso puede ser lo que quieres, pero a veces no.

Método Nº 5. Usando la variable de contexto ROW_COUNT

Desde la versión 1.5 Firebird dispone de una variable de contexto llamada ROW_COUNT que contiene la cantidad de filas afectadas por la última instrucción DML (INSERT, DELETE, UPDATE, SELECT, FETCH) en el actual stored procedure, trigger o execute block.

Podemos aprovecharnos de eso para numerar las filas de un SELECT. Por ejemplo, podríamos crear un stored procedure seleccionable para conseguir ese efecto:

CREATE PROCEDURE NUMEROREGISTRO
   RETURNS(
      tnNumero INTEGER,
      tcNombre CHAR(80))
AS
BEGIN

   FOR SELECT
      ROW_COUNT,
      P.PRD_NOMBRE
   FROM
      PRODUCTOS P
   INTO
      :tnNumero,
      :tcNombre
   DO BEGIN
      SUSPEND;
   END

END;

Como se trata de un stored procedure seleccionable para ejecutarlo deberíamos escribir algo como:

SELECT
   *
FROM
   NUMEROREGISTRO

El defecto de este método es que necesitas crear un stored procedure seleccionable para que funcione.

Método Nº 6. Usando una variable local

En este método dentro de un stored procedure seleccionable o de un execute block seleccionable usamos una variable local en la cual vamos guardando el número de la fila que se le va mostrando al usuario.

SET TERM ^ ;

CREATE PROCEDURE NUMERAR_FILAS
   RETURNS(
      tnOrdenx INTEGER,
      tnIdenti BIGINT,
      tcNombre VARCHAR(60))
AS
BEGIN

   tnOrdenx = 0;

   FOR SELECT BAN_IDENTI, BAN_NOMBRE FROM BANCOS INTO :tnIdenti, :tcNombre DO BEGIN
      tnOrdenx = tnOrdenx + 1;
      SUSPEND;
   END

END^

SET TERM ; ^

Como puedes ver, en la variable tnOrdenx se va colocando el número de la fila, y como la variable tnOrdenx es una de las que retorna este stored procedure seleccionable para el usuario que observa el resultado del SELECT es como si se tratara de una columna más.

El defecto de este método es que necesitas escribir un stored procedure seleccionable o un execute block para utilizarlo.

Conclusión:

Estos son los seis principales métodos para obtener el número de las filas que devuelven los SELECT, hay otros métodos e inclusive podrías inventar el tuyo propio, pero con lo expuesto hasta aquí ya debería ser suficiente si alguna vez deseas ver a las filas de tu SELECT numeradas. Como ves, ningún método es perfecto, todos tienen alguna desventaja, pero con Firebird es posible numerar a las filas.

Artículos relacionados:

https://firebird21.wordpress.com/2013/04/14/rdbset_context/

https://firebird21.wordpress.com/2013/04/13/rdbget_context

Anuncios