Inicio > SQL > Recursividad en PL/SQL – Un ejemplo

Recursividad en PL/SQL – Un ejemplo

El PL/SQL, como la mayoría de lenguajes modernos, nos permite implementar algoritmos recursivos en nuestros procesos. En los modelos relacionales de base de datos, es frecuente encontrarse con estructuras reflexivas. La recursividad nos facilita la programación de tareas que afectan a estos tipos de construcciones. A continuación presentamos un escenario donde aplicando recursividad disminuye la complejidad del proceso.

Hemos diseñado un sistema sencillo que almacena documentos en carpetas. El modelo simplificado de nuestro sistema es el siguiente:

Modelo "Carpetas"

Como se puede observar, una carpeta puede contener otras carpetas, y estas a su vez, otras. El usuario puede guardar una estructura como la que sigue:

Estructura de carpetas

Se requiere un proceso que sea capaz de borrar una carpeta y todo su contenido (sus documentos y sus subcarpetas). Para ello, crearemos un PL que hará uso de la recursividad:

-- Para una carpeta concreta, borra sus documentos y sus subcarpetas.
-- Si las subcarpetas contiene documentos o subcarpetas, también son borradas.
--
-- El proceso se llama a si mismo de forma recursiva para cada una de las
-- subcarpetas de la carpeta indicada.
--
-- %param P_ID_CARPETA Id. de la carpeta a borrar
--
PROCEDURE BORRAR_CARPETA (P_ID_CARPETA    CARPETA.ID_CARPETA%TYPE) IS

Cursor cCptHij is
Select cpt.ID_CARPETA
from CARPETA cpt
where cpt.ID_CARPETA_PADRE = P_ID_CARPETA;
BEGIN
-- Primero debemos borrar las carpetas hijas y sus documentos
For rCptHij in cCptHij loop
BORRAR_CARPETA (rCptHij.ID_CARPETA);
end loop;

-- Una vez borradas la posibles carpetas hijas, borramos
-- los documentos de la carpeta y luego ésta
Delete from DOCUMENTO doc
where doc.ID_CARPETA = P_ID_CARPETA;

Delete from CARPETA cpt
where cpt.ID_CARPETA = P_ID_CARPETA;
END;

El proceso consiste en comprobar si la carpeta a borrar tiene subcarpetas, en cuyo caso, se llama a si mismo para eliminarlas.

De este modo tan sencillo hemos solucionado el problema planteado. Si no hubiéramos hecho uso de la recursividad, habríamos tenido que crear un PL más complejo, con un número máximo de niveles de subcarpetas a controlar.

En definitiva, hemos visto como el PL/SQL permite recursividad y también como ésta es útil para tratar datos jerárquicos.

Adjunto los scripts utilizados para aquellos que quieran probarlo.

CREATE TABLE DOCUMENTO
( ID_DOCUMENTO NUMBER(8, 0) NOT NULL
, NOMBRE VARCHAR2(256) NOT NULL
, ID_CARPETA NUMBER(8, 0)
, CONSTRAINT DOCUMENTO_PK PRIMARY KEY (ID_DOCUMENTO) ENABLE);

CREATE TABLE CARPETA
( ID_CARPETA NUMBER(8, 0) NOT NULL
, NOMBRE VARCHAR2(256) NOT NULL
, ID_CARPETA_PADRE NUMBER(8, 0)
, CONSTRAINT CARPETA_PK PRIMARY KEY (ID_CARPETA) ENABLE);

ALTER TABLE DOCUMENTO
ADD CONSTRAINT DOCUMENTO_CARPETA_FK FOREIGN KEY (ID_CARPETA)
                             REFERENCES CARPETA (ID_CARPETA) ENABLE;

ALTER TABLE CARPETA
ADD CONSTRAINT CARPETA_CARPETA_FK FOREIGN KEY (ID_CARPETA_PADRE)
                             REFERENCES CARPETA (ID_CARPETA)ENABLE;

-- CARPETAS

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (1, 'Documentos', null);

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (2, 'Reuniones', 1);

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (3, 'Actas', 2);

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (4, '200100325', 3);

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (5, '200100331', 3);

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (6, 'Mañana', 5);

insert into carpeta (ID_CARPETA, NOMBRE, ID_CARPETA_PADRE)
values (7, 'Tarde', 5);

-- DOCUMENTOS

insert into documento (ID_DOCUMENTO, NOMBRE, ID_CARPETA)
values (1, 'acta.doc', 4);

insert into documento (ID_DOCUMENTO, NOMBRE, ID_CARPETA)
values (2, 'puntos_del_dia.doc', 4);

insert into documento (ID_DOCUMENTO, NOMBRE, ID_CARPETA)
values (3, 'presentacion.ppt', 4);

insert into documento (ID_DOCUMENTO, NOMBRE, ID_CARPETA)
values (4, 'acta_mañana.doc', 6);

insert into documento (ID_DOCUMENTO, NOMBRE, ID_CARPETA)
values (5, 'acta_tarde.doc', 7);

Categorías:SQL Etiquetas: , ,
  1. octubre 21, 2011 en 06:52

    muy buen aporte gracias es lo que estaba buscando

  2. diciembre 22, 2012 en 22:37

    I have been surfing online more than 4 hours today, yet
    I never found any interesting article like yours.
    It’s pretty worth enough for me. In my view, if all site owners and bloggers made good content as you did, the internet will be much more useful than ever before.

  3. Favian
    mayo 23, 2013 en 22:44

    very good the example, i needed an example…. thanks you

  1. noviembre 22, 2010 en 12:44
  2. noviembre 28, 2010 en 15:18
  3. enero 3, 2011 en 13:07
  4. enero 2, 2012 en 10:39
  5. enero 2, 2014 en 09:46

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: