Ejemplos prácticos de PL/SQL: cursores, bucles y control de transacciones
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.
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 HTMLPreguntas 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
Preguntas generadas con IA a partir del documento: comprueba las respuestas con el texto.