2 Pl SQL Cursores Oracle 11g
-
Upload
robert-puican-gutierrez -
Category
Documents
-
view
269 -
download
2
description
Transcript of 2 Pl SQL Cursores Oracle 11g
-
PL/SQL EN ORACLE
PL / SQLCURSORES
-
CURSORES
Si una sentencia SELECT devuelve ms de una fila*,se debe usar un cursor para su procesamiento enPL/SQL.
Para declarar y usar un cursor se siguen estos pasos:
1. Declarar el cursor: Se le asigna un nombre alcursor y se le asocia una consulta
2. Abrir el cursor: Se ejecuta la consulta; en esemomento se est apuntando a la primera de las filasseleccionadas por la consulta
3. Recuperar, tomar las filas del cursor una a una
4. Cerrar el cursor: Liberar la memoria
Proceso
iterativo
* Los cursores funcionan para cualquier consulta ya sea que esta
devuelva 0, 1 o muchas filas
-
CURSOR
Sintaxis:
CURSOR nombre_cursor -- Se declaraIS consulta SQL;
OPEN nombre_cursor; -- Se abreFETCH nombre_cursorINTO 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 ejecutadorecuper datos (trajo una fila)
%ROWCOUNT: Devuelve el nmero de filas ledas hasta elmomento
%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, nihacerles 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 cursoras:
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;
LOOP
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;
/
Todos los datos de un
empleado quedan almacenados
en mi_e
-
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
DECLARE
CURSOR emp_c IS SELECT dep FROM empleado FOR UPDATE;
BEGIN
FOR mi_e IN emp_c
LOOP
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
WHERE CURRENT OF emp_c;
END IF;
END LOOP;
END;
/
FOR UPDATE bloquea las filas ledas por el cursor antes* de hacer el UPDATE o
el DELETE
Al abrir, el cursor toma
una imagen de las filas
y las bloquea
* Si no hay FOR UPDATE, Oracle bloquea las filas en el momento de hacer el
UPDATE o el DELETE. FOR UPDATE establece el bloqueo desde el OPEN.
Para usar CURRENT OF el cursor debe ser FOR UPDATE.