Ejemplos prácticos de PL/SQL: cursores, bucles y control de transacciones

InformáticaActualizado el 5,57 KB

Resumen

Recopilación de bloques anónimos y procedimientos en Oracle PL/SQL que ilustran el uso de cursores explícitos y parametrizados, el control transaccional con SAVEPOINT, COMMIT y ROLLBACK, y estructuras de bucle como LOOP con EXIT WHEN y FOR con REVERSE. Incluye además un ejemplo de análisis numérico sobre un rango de enteros. Sirve para revisar la sintaxis básica y los patrones habituales de programación procedimental en la base de datos.

Puntos clave

  • Un cursor parametrizado recibe un valor al abrirse, como en C_MAX_GOL_SEL(EQUIPO_JUGADOR), lo que permite reutilizar la misma consulta para distintos equipos.
  • FETCH ... INTO carga la fila actual del cursor y EXIT WHEN cursor%NOTFOUND termina el bucle cuando no quedan filas.
  • SAVEPOINT marca un punto de control dentro de la transacción; ROLLBACK TO deshace solo los cambios posteriores a ese punto.
  • COMMIT confirma de forma permanente los cambios de la transacción en la base de datos.
  • Un bucle LOOP sin FOR necesita una condición de salida explícita mediante EXIT WHEN para no ejecutarse indefinidamente.
  • FOR i IN REVERSE a..b recorre el rango de forma descendente, de b hasta a.

Ponte a prueba

Ejemplos Prácticos de Programación en Oracle PL/SQL

A continuación, se presentan diversos bloques anónimos y procedimientos en PL/SQL estructurados y corregidos para ilustrar el uso de cursores, control de flujo transaccional y procesamiento de datos numéricos.

1. Procedimiento con Cursores Anidados: Obtención de Máximos Goleadores

Este bloque declara un procedimiento local que utiliza un cursor explícito y un cursor parametrizado para listar los principales goleadores según el equipo seleccionado:

DECLARE
    PROCEDURE OBTENER_JUGADORES(SELECCION VARCHAR2) IS
        V_EQUIPO JUGADOR.EQUIPO_JUGADOR%TYPE;
        CURSOR C_SELECCION IS
            SELECT EQUIPO_JUGADOR
            FROM JUGADOR
            WHERE SELECCION = SELECCION;
        CURSOR C_MAX_GOL_SEL (EQUIPO_JUGADOR JUGADOR.EQUIPO_JUGADOR%TYPE) IS
            SELECT NOMBRE, COUNT(*) AS GOLES
            FROM JUGADOR J
            INNER JOIN GOL G ON J.NOMBRE = G.JUGADOR_GOL
            WHERE J.EQUIPO_JUGADOR = EQUIPO_JUGADOR
            GROUP BY J.NOMBRE
            ORDER BY GOLES DESC;
        R_MAX_GOL C_MAX_GOL_SEL%ROWTYPE;
    BEGIN
        OPEN C_SELECCION;
        LOOP
            FETCH C_SELECCION INTO V_EQUIPO;
            EXIT WHEN C_SELECCION%NOTFOUND;

            DBMS_OUTPUT.PUT_LINE('');
            DBMS_OUTPUT.PUT_LINE(V_EQUIPO);
            DBMS_OUTPUT.PUT_LINE('-----------------');

            OPEN C_MAX_GOL_SEL(V_EQUIPO);
            FOR i IN 1..5 LOOP
                FETCH C_MAX_GOL_SEL INTO R_MAX_GOL;
                EXIT WHEN C_MAX_GOL_SEL%NOTFOUND;
                DBMS_OUTPUT.PUT_LINE(R_MAX_GOL.NOMBRE || '   ' || R_MAX_GOL.GOLES);
            END LOOP;
            CLOSE C_MAX_GOL_SEL;
        END LOOP;
        CLOSE C_SELECCION;
    EXCEPTION
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
    END OBTENER_JUGADORES;
BEGIN
    OBTENER_JUGADORES('UNO');
END;
/

2. Gestión de Transacciones con Savepoint y Control de Excepciones

Uso de puntos de control (SAVEPOINT), confirmación (COMMIT) y reversión selectiva (ROLLBACK TO) para preservar la integridad transaccional:

BEGIN
    -- Iniciar una transacción
    SAVEPOINT inicio_transaccion;

    -- Realizar modificaciones en la base de datos
    UPDATE tabla SET columna = valor WHERE condicion;

    -- Confirmar la transacción
    COMMIT;
EXCEPTION
    -- Manejar cualquier excepción
    WHEN OTHERS THEN
        -- Deshacer la transacción en caso de error
        ROLLBACK TO inicio_transaccion;
END;
/

3. Bloque Transaccional Adicional

Segundo bloque anónimo para el tratamiento seguro de transacciones en base de datos:

BEGIN
    -- Iniciar una transacción
    SAVEPOINT inicio_transaccion;

    -- Realizar modificaciones en la base de datos
    UPDATE tabla SET columna = valor WHERE condicion;

    -- Confirmar la transacción
    COMMIT;
EXCEPTION
    -- Manejar cualquier excepción
    WHEN OTHERS THEN
        -- Deshacer la transacción en caso de error
        ROLLBACK TO inicio_transaccion;
END;
/

4. Estructura de Bucle Básico con Condición de Salida

Implementación de un bucle iterativo elemental mediante LOOP y salida condicional con EXIT WHEN:

DECLARE
    contador NUMBER := 1;
BEGIN
    LOOP
        -- Código a ejecutar en cada iteración
        DBMS_OUTPUT.PUT_LINE('Iteración: ' || contador);
        
        -- Incrementar el contador
        contador := contador + 1;
        
        -- Salir del bucle cuando se cumple la condición
        EXIT WHEN contador > 5;
    END LOOP;
END;
/

5. Análisis Estadístico y Rango Numérico con Bucle Reverse

Procesamiento de dos valores numéricos ingresados mediante variables de sustitución, validación de valores nulos, ordenamiento y recorrido descendente evaluando paridad y signo:

DECLARE
    NUMERO1   NUMBER := &NUMERO1;
    NUMERO2   NUMERO1%TYPE := &NUMERO2;
    SUMA      NUMBER := 0;
    CONTAR    NUMBER := 0;
    POSITIVOS NUMBER := 0;
    NEGATIVOS NUMBER := 0;
    PARES     NUMBER := 0;
    IMPARES   NUMBER := 0;
    AUX       NUMBER;
BEGIN
    -- Comprobar valores nulos
    IF NUMERO1 IS NULL AND NUMERO2 IS NULL THEN
        NUMERO1 := -5;
        NUMERO2 := 5;
    END IF;
    IF NUMERO1 IS NULL THEN
        NUMERO1 := -5;
    END IF;
    IF NUMERO2 IS NULL THEN
        NUMERO2 := -5;
    END IF;

    -- Comprobar cuál valor es mayor para asegurar el rango
    IF NUMERO1 > NUMERO2 THEN
        AUX := NUMERO1;
        NUMERO1 := NUMERO2;
        NUMERO2 := AUX;
    END IF;
    
    -- Recorrido en orden inverso del rango establecido
    FOR I IN REVERSE NUMERO1..NUMERO2
    LOOP
        DBMS_OUTPUT.PUT(I || ' ');
        
        CONTAR := CONTAR + 1;
        SUMA := SUMA + I;
        
        IF I >= 0 THEN
            POSITIVOS := POSITIVOS + 1;
        ELSE 
            NEGATIVOS := NEGATIVOS + 1;
        END IF;
        
        IF MOD(I, 2) = 0 THEN
            PARES := PARES + 1;
        ELSE
            IMPARES := IMPARES + 1;
        END IF;
    END LOOP;
    
    DBMS_OUTPUT.PUT_LINE('');
    DBMS_OUTPUT.PUT_LINE('Hay ' || CONTAR || ' números');
    DBMS_OUTPUT.PUT_LINE('La suma es: ' || SUMA);
    DBMS_OUTPUT.PUT_LINE('Hay ' || POSITIVOS || ' números positivos');
    DBMS_OUTPUT.PUT_LINE('Hay ' || NEGATIVOS || ' números negativos');
    DBMS_OUTPUT.PUT_LINE('Hay ' || PARES || ' números pares');
    DBMS_OUTPUT.PUT_LINE('Hay ' || IMPARES || ' números impares');
END;
/

Descargar

PDF Word HTML

Preguntas frecuentes

¿Para qué sirve SAVEPOINT en PL/SQL?

SAVEPOINT establece un punto de control dentro de una transacción. Si después ocurre un error, ROLLBACK TO permite deshacer únicamente las operaciones realizadas desde ese punto.

¿Cómo se termina un bucle LOOP en PL/SQL?

Se utiliza la sentencia EXIT WHEN seguida de una condición; cuando la condición se cumple, el bucle finaliza. Sin esa condición el bucle no tendría fin.

¿Qué hace FOR i IN REVERSE en PL/SQL?

Recorre un rango de enteros en orden descendente, desde el límite superior hasta el inferior. Por ejemplo, FOR i IN REVERSE 1..3 produce los valores 3, 2 y 1.

Ponte a prueba

Tarjetas de repaso

Pulsa una tarjeta para ver la respuesta.

Test

1. ¿Qué atributo de un cursor indica que no quedan más filas por leer?
2. ¿Qué sentencia confirma de forma permanente los cambios de una transacción?
3. En el bloque de transacciones, ¿qué ocurre si se produce una excepción?
4. ¿Qué mostraría el bucle con contador inicial 1 y condición EXIT WHEN contador > 5?
5. ¿Qué significa un cursor parametrizado?
6. En el bloque estadístico, ¿qué condición clasifica un número como positivo?

Preguntas generadas con IA a partir del documento: comprueba las respuestas con el texto.