Con Firebird podemos escribir stored procedures recursivos, si los necesitamos.

¿Qué significa la recursividad?

Que el mismo stored procedure se ejecuta una vez, y otra vez, y otra vez, y otra vez … hasta que se cumple una condición que lo detiene.

¿Por qué usar la recursividad?

Todos los algoritmos recursivos pueden escribirse también sin usar recursividad, no es obligatorio usarla, en ningún caso. La ventaja es que en muchos casos los algoritmos recursivos son mucho más cortos y más fáciles de entender. También pueden ser más rápidos. En contrapartida casi siempre ocupan más memoria que sus equivalentes no recursivos.

Hay gente a quien le cuesta mucho pensar en forma recursiva y hay gente a quien le resulta muy fácil pensar así. Si para tí no es difícil pensar en forma recursiva entonces que el Firebird te provea de esta característica te puede ser muy útil.

¿Qué se debe tener en cuenta al escribir un stored procedure recursivo?

  1. Que debe existir una condición para que la recursividad se detenga
  2. Que cada vez que se ejecuta el stored procedure se debe estar más cerca de esa condición

Ejemplo 1:

Un ejemplo clásico para mostrar la recursividad es el utilizado para hallar el factorial de un número. Como quizás recordarás, el factorial de un número es ese número multiplicado por todos los anteriores números naturales, desde el 1.

El factorial de 1 es 1

El factorial de 2 es 1 * 2 = 2

El factorial de 3 es 1 * 2 * 3 = 6

El factorial de 4 es 1 * 2 * 3 * 4 = 24

El factorial de 5 es 1 * 2 * 3 * 4 * 5 = 120

El factorial de 6 es 1 * 2 * 3 * 4 * 5 * 6 = 720

y así sucesivamente.

SET TERM ^ ;

CREATE PROCEDURE FACTORIAL(
   tnNumero INTEGER)
RETURNS(
   ftnResultado DOUBLE PRECISION)
AS
BEGIN

   IF (tnNumero = 1) THEN BEGIN
      ftnResultado = 1;
      SUSPEND;
   END ELSE BEGIN
      EXECUTE PROCEDURE FACTORIAL (tnNumero - 1) RETURNING_VALUES ftnResultado;
      ftnResultado = ftnResultado * tnNumero;
      SUSPEND;
   END

END^

SET TERM ; ^

Aquí la condición de fin es que el número recibido como parámetro de entrada sea 1. El stored procedure se va ejecutando cada vez con el número anterior, hasta que se llega al 1 y allí se termina. Por ejemplo, si le envías el número 6, el stored procedure se ejecutará 6 veces y sus parámetros de entrada serán: 6, 5, 4, 3, 2, 1

Ejemplo 2:

Otro ejemplo clásico es hallar el número de Fibonacci. Esta es una serie infinita de números naturales. La serie empieza con los números 0 y 1. A partir de allí, cada número es la suma de los dos anteriores. Esto nos da:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, etc.

SET TERM ^ ;

CREATE PROCEDURE FIBONACCI(
   tnNumero INTEGER)
RETURNS(
   ftnResultado DOUBLE PRECISION)
AS
   DECLARE VARIABLE lnNumero1 INTEGER;
   DECLARE VARIABLE lnNumero2 INTEGER;
BEGIN

   IF (tnNumero < 2) THEN BEGIN
      ftnResultado = tnNumero;
      SUSPEND;
   END ELSE BEGIN
      EXECUTE PROCEDURE FIBONACCI(tnNumero - 1) RETURNING_VALUES lnNumero1;
      EXECUTE PROCEDURE FIBONACCI(tnNumero - 2) RETURNING_VALUES lnNumero2;
      ftnResultado = lnNumero1 + lnNumero2;
      SUSPEND;
   END

END^

SET TERM ; ^

En este caso la recursividad se detendrá cuando el parámetro de entrada recibido sea menor que 2.

CUIDADO:

Siempre antes de llamar a un stored procedure recursivo hay que validar que el número (o los números) que se envía como parámetro de entrada no provoque una recursividad infinita. En el ejemplo del factorial algo así ocurriría si se envía como parámetro de entrada a un número negativo. ¿Por qué? porque en ese caso en lugar de acercarse a  la condición de fin, cada vez se alejará más. Por ejemplo, si le enviamos como parámetro de entrada al número -6, sus siguientes valores serán -7, -8, -9, -10, – 11, -12, etc., o sea que en lugar de acercarse a la condición de fin (que el parámetro de entrada sea 1) se aleja cada vez más. Al enviarle como parámetro de entrada a un número negativo, cada recursión se aleja más de la condición de fin.

Artículo relacionado:

El índice del blog Firebird21