You are on page 1of 21

Cursores y Transacciones

A.M.M(2018)
Cursor

Herramienta principal del PL/SQL.


Útiles para gestionar grandes cantidades de datos).
Está formado por un conjunto de registros devueltos
por una instrucción SQL de tipo SELECT.
Son segmentos de memoria utilizados para realizar
operaciones con las filas de datos recuperados
Cursores Implícitos
• Se usan con la sentencia SELECT …. INTO
• Deben devolver una sola fila, sino devolverá error

DECLARE
lcalumno alumno.calumno%TYPE;
lnombre alumno.lnombre.nombre%TYPE;
BEGIN
SELECT calumno, nombre
INTO lcalumno, lnombre
FROM alumno
WHERE calumno = '19828509K';
/* Resto de sentencias de bloque */
END;
Cursores Explícitos
• Se utiliza si la sentencia SELECT devuelve varios
registros.
• Se define como cualquier otra variable y admiten
parámetros.
• Operaciones Básicas :
• Declaración : CURSOR <nombre_c> IS <Sent _SELECT>
• Apertura : OPEN <nombre_c>
• Recogida : FETCH <nombre_c> INTO {<var> |<lista_v>}
• Cierre : CLOSE <nombre_c>
Para controlar la ejecución de un cursor explicito :

•%ISOPEN : Devuelve “true” si el cursor está abierto.


•%FOUND : Devuelve “true” si el registro fue
satisfactoriamente procesado.
•%NOTFOUND : Devuelve true si el registro no pudo ser
procesado . Normalmente esto ocurre cuando ya se han
procesado todos los registros devueltos por el cursor.
•%ROWCOUNT: Devuelve el número de registros que
han sido procesados hasta ese momento.

En cursores implícitos se antepone SQL antes del


atributo
NOTA:
a) Para ver los errores de compilación:
show errors procedure nombreprocedure;

b) Mostrar la ejecución por pantalla :


SET SERVEROUTPUT ON SIZE UNLIMITED;

c) Ejecutar el procedimiento :
Begin
nombreprocedimento(parámeto);
end;
/;
Execute nombreprocedimiento (parámetro) ;

d) Eliminar el procedimiento:
drop procedure nombreprocedimiento;
Ejemplo1. Crear un procedimiento que muestre por
consola las notas del alumno : 19828509K.
CREATE OR REPLACE PROCEDURE informe_notas
AS
CURSOR c_nota IS
SELECT * FROM notasalumno
WHERE calumno = '19828509K';
v_reg_nota c_nota%ROWTYPE;
BEGIN
OPEN c_nota;
FETCH c_nota INTO v_reg_nota;
WHILE c_nota%FOUND LOOP
DBMS_OUTPUT.PUT_LINE ( 'CODIGO : ' ||v_reg_nota.calumno||' PERIODO ' ||
v_reg_nota.cperiodo|| ' CURSO ‘||v_reg_nota.curso.ccurso||
‘ SECCION ' ||v_reg_nota.cseccion||' NOTA ' || v_reg_nota.nota);
FETCH c_nota INTO v_reg_nota;
END LOOP;
CLOSE c_nota;
END;
/
Ejemplo 2. Crear un procedimiento que muestre las notas
de un alumno cuyo código ingresa como parámetro.

CREATE OR REPLACE PROCEDURE Informe_nota1


(codigo notasalumno.calumno%TYPE)
IS
CURSOR c_notalu IS
SELECT * FROM notasalumno WHERE calumno = codigo;
v_reg notasalumno%ROWTYPE;
BEGIN
OPEN c_notalu;
FETCH c_notalu INTO v_reg;
WHILE c_notalu%FOUND LOOP
DBMS_OUTPUT.PUT_LINE ( 'El alumno con código ' ||v_reg.calumno||'
tiene las siguientes notas :PER ' ||v_reg.cperiodo||' CUR' ||v_reg.ccurso|| 'SEC '
||v_reg.cseccion||' NOTA ' ||v_reg.nota);
FETCH c_notalu INTO v_reg;
END LOOP;
CLOSE c_notalu;
END;
/
Ejemplo 3. CURSOR SIMPLIFICADO, uso del FOR :Crear un
procedimiento que muestre las notas de un alumno, el código
ingresa como parámetro

CREATE OR REPLACE PROCEDURE Informe_nota2


(codigo notasalumno.calumno%TYPE)
IS
CURSOR c_notalu IS
SELECT * FROM notasalumno WHERE calumno = codigo;
v_reg notasalumno%ROWTYPE;
BEGIN
FOR v_reg IN c_notalu LOOP
DBMS_OUTPUT.PUT_LINE ( 'El alumno con código ' ||v_reg.calumno||'
tiene las siguientes notas :PER ' ||v_reg.cperiodo||' CUR' ||v_reg.ccurso|| 'SEC '
||v_reg.cseccion||' NOTA ' ||v_reg.nota);
END LOOP;
END;
/
Ejemplo 4. Crear un procedimiento que muestre todas las notas
pendientes de calificar de un alumno.
CREATE OR REPLACE PROCEDURE informe_alumno
(codigo notasalumno.calumno%TYPE)
IS
CURSOR c_notalu IS
SELECT * FROM notasalumno WHERE calumno = codigo;
nombre alumno.nombrealumno%TYPE;
estado VARCHAR (30);
BEGIN
SELECT nombrealumno INTO nombre FROM alumno wHERE calumno = codigo;
DBMS_OUTPUT.PUT_LINE (' NOMBRE :' || nombre);
FOR v_reg IN c_notalu LOOP
IF v_reg.ccalificacion = '9' THEN
estado := ' Pendiente de Calificacion ';
ELSE
estado := '';
END IF;
DBMS_OUTPUT.PUT_LINE (v_reg.cperiodo||' '||v_reg.ccurso||' '||v_reg.cseccion ||
' '|| v_reg.nota|| ' '||estado );
END LOOP;
DBMS_OUTPUT.PUT (' FIN ');
END;
/
Ejemplo 5. Crear un procedimiento que muestre todas
las notas pendientes de calificar de un alumno.
CREATE OR REPLACE PROCEDURE aumentar_nota(
vp_periodo notasalumno.cperiodo%TYPE,
vp_curso notasalumno.ccurso%TYPE,
vp_seccion notasalumno.cseccion%TYPE,
vp_aumento number)
AS
CURSOR c_alum IS SELECT cperiodo, ccurso, cseccion, nota FROM notasalumno
WHERE cperiodo = vp_periodo
AND ccurso = vp_curso
AND cseccion = vp_seccion
FOR UPDATE;
vc_reg_alu c_alum%ROWTYPE;
v_inc NUMBER ;
BEGIN
OPEN c_alum;
FETCH c_alum INTO vc_reg_alu;
WHILE c_alum%FOUND LOOP
v_inc := (vc_reg_alu.nota/100)* vp_aumento;
UPDATE notasalumno SET nota = nota + 1
WHERE CURRENT OF c_alum;
FETCH c_alum INTO vc_reg_alu;
END LOOP;
END ;
/
Ejemplo 6 FUNCIONES
CREATE OR REPLACE FUNCTION fn_hoydia_manana (manana IN OUT DATE)
RETURN DATE IS
hoydia DATE;
BEGIN
SELECT CURRENT_DATE INTO hoydia FROM dual;
SELECT hoydia + 1 INTO manana FROM dual;
RETURN hoydia;
END fn_hoydia_manana;
/
---Una vez creada nuestra función y ejecutada, veremos como utilizarla en un bloque anónimo.

SET SERVEROUTPUT ON SIZE UNLIMITED;


DECLARE
hoydia DATE;
manana DATE;
BEGIN
hoydia := fn_hoydia_manana(
manana => manana
);
dbms_output.put_line(hoydia);
dbms_output.put_line(manana);
END;
/
Ejemplo 7 FUNCIONES Teniendo como dato el código de un curso,
encontrar la descripción del curso.

CREATE OR REPLACE Function NombreCurso


( codigo_in IN cursos.ccurso%TYPE)
RETURN VARCHAR2
IS
cnombre VARCHAR2(50);
CURSOR c1
IS
SELECT dcurso
FROM cursos
WHERE ccurso = codigo_in;
BEGIN
OPEN c1;
FETCH c1 INTO cnombre;
IF c1%NOTFOUND THEN
cnombre := 'no hay';
END IF;
CLOSE c1;
RETURN cnombre;
END;
/
EXCEPCIONES
Tratamiento de errores.

• Sirven para tratar errores en tiempo de ejecución.


• Cuando se produce el error se pasa el control a la sección
EXCEPTION.
• Se busca un manejador WHEN para el caso concreto
(OTHERS para el resto)
• Existen Excepciones internas predefinidas (Manual Oracle)
• Existen Excepciones definidas por el usuario:
o Declaración: <nombre_excep> EXCEPTION.
o Disparo: RAISE<nombre_excep>.
Ejemplos de Exception:

DECLARE
------Declaraciones
BEGIN
------Ejecución
EXCEPTION
WHEN NO_DATA_FOUND THEN
--Se ejecuta cuando ocurre una excepción de este tipo.
WHEN ZERO_DIVIDE THEN
-- Se ejecuta cuando ocurre una excepción de este tipo.
WHEN OTHERS THEN
-- Se ejecuta cuando ocurre una excepción de un tipo no
tratado en los bloques anteriores.
END;
/
Ejemplo 8 Procedimiento que inserta registros a la tabla notasalumno .
CREATE OR REPLACE PROCEDURE INSERTA_ALUMNO(
p_periodo IN notasalumno.cperiodo%TYPE,
p_curso IN notasalumno.ccurso%TYPE,
p_seccion IN notasalumno.cseccion%TYPE,
p_calumno IN notasalumno.calumno%TYPE,
p_nota IN notasalumno.nota%TYPE)
IS
ccali notasalumno.ccalificacion%TYPE;
BEGIN
CASE
WHEN p_nota < 0 THEN ccali := '' ;
WHEN p_nota < 10 THEN ccali := '0' ;
WHEN p_nota < 15 THEN ccali := '1' ;
WHEN p_nota < 18 THEN ccali := '2' ;
WHEN p_nota < 21 THEN ccali := '3' ;
ELSE ccali := '' ;
END CASE ;
INSERT INTO notasalumno (cperiodo,ccurso,cseccion,calumno,nota,ccalificacion)
VALUES (p_periodo,p_curso,p_seccion,p_calumno, p_nota,ccali);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20001, 'Ha intentado insertar un duplicado de notasalumno');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20002, 'Se ha producido un error al insertar un notasalumno.');
END;
/
Transacción

Una transacción es un conjunto de


sentencias SQL que se ejecutan en una
base de datos como una UNICA OPERACIÓN
(todo o nada), confirmándose o
deshaciéndose todo el conjunto de
sentencias SQL. La transacción puede
quedar finalizada (con las sentencias
apropiadas) o implícitamente (terminando la
sesión).
Transacción
Durante la transacción, todas las modificaciones que hagamos
sobre base de datos, no son definitivas, más concretamente, se
realizan sobre un tablespace especial que se denomina
tablespace de ROLLBACK, o RBS (RollBack Segment).
En este tablespace se reserva un espacio para cada sesión
activa en el servidor, y es en ese espacio donde se almacenan
todas las modificaciones de cada transacción.
Una vez que la transacción se ha finalizado, las modificaciones
temporales almacenadas en el RBS, se vuelcan al tablespace
original, donde está almacenada nuestra tabla.
Esto permite que ciertas modificaciones que se realizan en varias
sentencias, se puedan validar todas a la vez, o rechazar todas a
la vez.
Transacción
• Dentro de una transacción se pueden crear los llamados
“punto de control” mediante la sentencia:
SAVEPOINT Nombre_punto_control;
• Las sentencias de finalización de transacción son:
• COMMIT: la transacción termina correctamente, se vuelcan los
datos al tablespace original y se vacía el RBS.
• ROLLBACK: se rechaza la transacción y el vacía el RBS.
Cualquier cambio realizado desde que se inició la
transacción se deshace, quedando la base de datos en el
mismo estado que antes de iniciarse la transacción.
• A la hora de hacer un ROLLBACK o un COMMIT se podrá
hacer hasta cierto punto con la sintaxis:
COMMIT TO punto_control;
ROLLBACK TO punto_control;
Transacción
Comandos.
• COMMIT [WORK];
Finaliza la transacción actual realizando todos los cambio
pendientes en la B.D.
• ROLLBACK [WORK];
Finaliza la transacción actual desechando todos los cambio
pendientes.
TRANSACCION

INSERT UPDATE INSERT DELETE

Savepoint A Savepoint B
COMMIT
ROLLBACK to
Savepoint B

ROLLBACK to Savepoint A
ROLLBACK
Transacción
SQL> create table foo( col1 number );
Table created.
SQL> insert into foo values( 1 );
1 row created.
SQL> savepoint after_insert;
Savepoint created.
SQL> delete from foo;
1 row deleted.
SQL> rollback to savepoint after_insert;
Rollback complete.
SQL> select * from foo;

COL1
---------- 1

You might also like