Vous êtes sur la page 1sur 13

<Insert Picture Here>

PL/SQL EN ORACLE

PL / SQL
CURSORES

CURSORES
Si una sentencia SELECT devuelve ms de una fila*,

se debe usar un cursor para su procesamiento en


PL/SQL.
Para declarar y usar un cursor se siguen estos pasos:
1. Declarar el cursor: Se le asigna un nombre al
cursor y se le asocia una consulta
2. Abrir el cursor: Se ejecuta la consulta; en ese
momento se est apuntando a la primera de las filas
seleccionadas por la consulta
3. Recuperar, tomar las filas del cursor una a una Proceso
iterativo
4. Cerrar el cursor: Liberar la memoria
* Los cursores funcionan para cualquier consulta ya sea que esta
devuelva 0, 1 o muchas filas

CURSOR
Sintaxis:
CURSOR nombre_cursor -- Se declara
IS consulta SQL;
OPEN nombre_cursor; -- Se abre
FETCH nombre_cursor
INTO var1,var2, ..., varn;
/*Se recupera la fila actual */
CLOSE nombre_cursor; -- Se cierra

CURSOR
Atributos (funciones) de los cursores:
%NOTFOUND: Es verdadero (TRUE) cuando el ltimo
FETCH ejecutado no recupera datos
%FOUND: Es verdadero cuando el ltimo FETCH ejecutado
recuper datos (trajo una fila)
%ROWCOUNT: Devuelve el nmero de filas ledas hasta el
momento
%ISOPEN: Es verdadero cuando el cursor est abierto

EJEMPLO CURSOR
DROP TABLE empleado;
CREATE TABLE empleado(
codigo NUMBER(8) PRIMARY KEY,
nombre VARCHAR2(15),
dep NUMBER(3),
sueldo NUMBER(8) NOT NULL
);
INSERT INTO empleado VALUES(12, 'Patty',1,100);
INSERT INTO empleado VALUES(15, 'Adam',2,300);
INSERT INTO empleado VALUES(76, 'Adrian',2,400);
INSERT INTO empleado VALUES(73, 'Ben',5,500);
INSERT INTO empleado VALUES(56, 'Lisa',3,100);

Ejemplo Cursor
DECLARE
CURSOR ordena_d IS
SELECT codigo, dep FROM empleado ORDER BY dep;
codi empleado.codigo%TYPE;
dpto empleado.dep%TYPE;
BEGIN
OPEN ordena_d;
LOOP
FETCH ordena_d INTO codi, dpto;
EXIT WHEN ordena_d%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(codi || '--' || dpto);
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total de Registros: ' || ordena_d%ROWCOUNT);
CLOSE ordena_d;
END;
/

CURSORES
Los cursores tambin se pueden procesar sin necesidad de abrirlos, ni
hacerles FETCH, ni cerrarlos explcitamente.
Estas acciones las puede hacer automticamente un ciclo FOR as:

DECLARE
CURSOR ordena_d IS --Se declara el cursor
SELECT codigo, dep FROM empleado ORDER BY dep;
BEGIN
FOR mi_e IN ordena_d LOOP
DBMS_OUTPUT.PUT_LINE(mi_e.codigo || ' ' || mi_e.dep);
END LOOP;
---DBMS_OUTPUT.PUT_LINE('Total: ' || ordena_d%ROWCOUNT);
END;
/
mi_e es una variable local del ciclo que
automticamente se declara del tipo del cursor

CURSOR SIN DECLARAR


Se puede tambin evitar la declaracin de un cursor
as:
BEGIN
FOR mi_e IN (SELECT codigo, dep
FROM empleado ORDER BY dep)
LOOP
DBMS_OUTPUT.PUT_LINE(mi_e.codigo || ' - ' || mi_e.dep);
END LOOP;
END;
/

CURSOR CON PARAMETRO


SET SERVEROUTPUT ON
DECLARE
total NUMBER(5); grantotal NUMBER(6) := 0;
CURSOR emp_cur(v_dept NUMBER) IS
SELECT nombre FROM empleado WHERE dep = v_dept;
BEGIN
FOR k IN 1..5 LOOP
DBMS_OUTPUT.PUT_LINE('Dpto ' || k);
total := 0;
FOR mi_e IN emp_cur(k) LOOP
DBMS_OUTPUT.PUT_LINE('Empleado: '|| mi_e.nombre);
total := total + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total empleados en el dpto: ' || total);
grantotal := grantotal + total;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total empleados en la empresa: ' || grantotal);
END;
/

ROWTYPE
Se puede declarar una variable del tipo de una tabla
(mediante ROWTYPE)y se puede usar as:
DECLARE
CURSOR emp_cur IS SELECT * FROM empleado;
mi_e empleado%ROWTYPE;
BEGIN
OPEN emp_cur;
Todos los datos de un
LOOP
empleado quedan almacenados
en mi_e
FETCH emp_cur INTO mi_e;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(mi_e.codigo || ' ' || mi_e.dep);
END LOOP;
CLOSE emp_cur;
END;
/

Tambin se pueden declarar variables del tipo de un cursor:

DECLARE
CURSOR ord_c IS
SELECT sueldo FROM empleado ORDER BY sueldo DESC;
mi_e ord_c%ROWTYPE;
suma NUMBER(6) := 0;
BEGIN
OPEN ord_c;
LOOP
FETCH ord_c INTO mi_e;
EXIT WHEN ord_c%NOTFOUND OR ord_c%ROWCOUNT = 3;
suma := suma + mi_e.sueldo;
END LOOP;
CLOSE ord_c;
DBMS_OUTPUT.PUT_LINE('Total: ' || suma );
END;
/
Qu hace este cdigo?

FOR UPDATE y CURRENT OF


Al abrir, el cursor toma
una imagen de las filas
y las bloquea

DECLARE
CURSOR emp_c IS SELECT dep FROM empleado FOR UPDATE;
BEGIN
FOR UPDATE bloquea las filas ledas por
FOR mi_e IN emp_c
el cursor antes* de hacer el UPDATE o
LOOP
el DELETE
IF mi_e.dep = 2 THEN
DELETE FROM empleado -- Se borran los emps actuales del depto 2
WHERE CURRENT OF emp_c; -- Se refiere a la fila actual del cursor
ELSE
UPDATE empleado SET dep = dep - 1
Para usar CURRENT OF el cursor
WHERE CURRENT OF emp_c;
debe ser FOR UPDATE.
END IF;
END LOOP;
* Si no hay FOR UPDATE, Oracle bloquea las filas en el momento de hacer el
END;
UPDATE o el DELETE. FOR UPDATE establece el bloqueo desde el OPEN.
/