Cursores en PL/SQL: ejemplos prácticos de declaración, FETCH y control de filas

Informática5,17 KB

Ejemplos de cursores en PL/SQL

A continuación se presentan varios ejemplos de cursores explícitos en PL/SQL, con el uso de atributos como %NOTFOUND, %ROWCOUNT y %ROWTYPE.

Ejemplo 35: Recorrer estudiantes de la carrera de Historia

En este bloque se declara un cursor que recupera el identificador, nombre y apellido de los estudiantes de la carrera de Historia.

DECLARE
  v_idestudiante estudiantes.idestudiante%TYPE;
  v_nombre estudiantes.nombre%TYPE;
  v_apellido estudiantes.apellido%TYPE;
  v_carrera estudiantes.carrera%TYPE := 'Historia';
  CURSOR c_estudiantes IS
    SELECT idestudiante, nombre, apellido
    FROM estudiantes
    WHERE carrera = v_carrera;
BEGIN
  /* Identificar las filas en el conjunto activo y preparar para el procesamiento posterior de los datos */
  OPEN c_estudiantes;
  LOOP
    /* Recuperar cada fila del conjunto activo en las variables PL/SQL */
    FETCH c_estudiantes INTO v_idestudiante, v_nombre, v_apellido;
    DBMS_OUTPUT.PUT_LINE(v_idestudiante || ' ' || v_nombre || ' ' || v_apellido);
    /* Si no hay más filas que mostrar, salir del loop */
    EXIT WHEN c_estudiantes%NOTFOUND;
  END LOOP;
  /* Liberar recursos de la consulta */
  CLOSE c_estudiantes;
END;

Nota: en este ejemplo la condición de salida se evalúa después del DBMS_OUTPUT, por lo que la última fila se muestra dos veces o el último registro vacío puede imprimirse. Conviene situar EXIT WHEN justo después del FETCH para evitarlo.

Ejemplo 36: Uso de %ROWTYPE con un cursor

DECLARE
  v_departamento asignaturas.departamento%TYPE;
  v_asignatura asignaturas.asignatura%TYPE;
  CURSOR c_asignaturas IS
    SELECT * FROM asignaturas;
  v_registroasignaturas c_asignaturas%ROWTYPE;
BEGIN
  OPEN c_asignaturas;
  FETCH c_asignaturas INTO v_registroasignaturas;
  DBMS_OUTPUT.PUT_LINE(v_registroasignaturas.departamento || ' ' ||
                       v_registroasignaturas.asignatura || ' ' ||
                       c_asignaturas%ROWCOUNT);
END;

Ejemplo 37: Cursor con parámetros

DECLARE
  CURSOR c_asignaturas(p_departamento asignaturas.departamento%TYPE,
                       p_asignatura asignaturas.asignatura%TYPE) IS
    SELECT * FROM asignaturas
    WHERE departamento = p_departamento
      AND asignatura = p_asignatura;
  v_registroasignaturas c_asignaturas%ROWTYPE;
BEGIN
  OPEN c_asignaturas('MAT', 102);
  FETCH c_asignaturas INTO v_registroasignaturas;
  DBMS_OUTPUT.PUT_LINE(v_registroasignaturas.departamento || ' ' ||
                       v_registroasignaturas.asignatura);
END;

Ejemplo 38: UPDATE seguido de INSERT (SQL%NOTFOUND y SQL%ROWCOUNT)

Se intenta actualizar una sala; si no existe, se inserta. Se muestran dos variantes equivalentes.

BEGIN
  UPDATE salas
  SET numero_asientos = 100
  WHERE id_sala = 20001;

  IF SQL%NOTFOUND THEN
    INSERT INTO salas (id_sala, numero_asientos)
    VALUES (20001, 100);
  END IF;
END;

BEGIN
  UPDATE salas
  SET numero_asientos = 100
  WHERE id_sala = 20001;

  IF SQL%ROWCOUNT = 0 THEN
    INSERT INTO salas (id_sala, numero_asientos)
    VALUES (20001, 100);
  END IF;
END;

Ejemplo 39: Manejo de NO_DATA_FOUND

DECLARE
  v_datossala salas%ROWTYPE;
BEGIN
  SELECT * INTO v_datossala
  FROM salas
  WHERE id_sala = -1;

  IF SQL%NOTFOUND THEN
    DBMS_OUTPUT.PUT_LINE('SQL%NOTFOUND es TRUE!');
  END IF;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND fue usado!');
END;

Ejemplo 40: Cursor con LOOP e inserciones

DECLARE
  v_idestudiante estudiantes.idestudiante%TYPE;
  v_nombre estudiantes.nombre%TYPE;
  v_apellido estudiantes.apellido%TYPE;
  CURSOR c_estudiantesdehistoria IS
    SELECT idestudiante, nombre, apellido
    FROM estudiantes
    WHERE carrera = 'Historia';
BEGIN
  OPEN c_estudiantesdehistoria;
  LOOP
    FETCH c_estudiantesdehistoria INTO v_idestudiante, v_nombre, v_apellido;
    EXIT WHEN c_estudiantesdehistoria%NOTFOUND;

    INSERT INTO estudiantes_registrados (idestudiante, departamento, asignatura)
    VALUES (v_idestudiante, 'MAT', 102);

    INSERT INTO tabla_temp (numero_columna, caracteres_columna)
    VALUES (v_idestudiante, v_nombre || ' ' || v_apellido);
  END LOOP;
  CLOSE c_estudiantesdehistoria;
END;

Ejemplo 41: Cursor con WHILE y %FOUND

DECLARE
  CURSOR c_estudiantesdehistoria IS
    SELECT idestudiante, nombre, apellido
    FROM estudiantes
    WHERE carrera = 'Historia';
  v_datosestudiante c_estudiantesdehistoria%ROWTYPE;
BEGIN
  OPEN c_estudiantesdehistoria;
  FETCH c_estudiantesdehistoria INTO v_datosestudiante;
  WHILE c_estudiantesdehistoria%FOUND LOOP
    INSERT INTO estudiantes_registrados (idestudiante, departamento, asignatura)
    VALUES (v_datosestudiante.idestudiante, 'MAT', 102);

    INSERT INTO tabla_temp (numero_columna, caracteres_columna)
    VALUES (v_datosestudiante.idestudiante,
            v_datosestudiante.nombre || ' ' || v_datosestudiante.apellido);

    FETCH c_estudiantesdehistoria INTO v_datosestudiante;
  END LOOP;
  CLOSE c_estudiantesdehistoria;
END;

Descargar

PDF Word HTML