Вы находитесь на странице: 1из 9

1 Cursores

Como sabemos el lenguaje SQL nos ayuda en PL/SL a manipular los datos mediante
consultas, cada vez que nosotros hacemos uso de consultas sql estamos usando cursores. De
la misma forma cuando insertamos registros, modificaciones o eliminaciones estamos
implcitamente haciendo uso de cursores. Por otro lado y en el uso mas representativo que se
le dan a los cursores es el procesamiento de un conjunto de registros a partir de una consulta
SQL.
Definicin: Un cursor es el nombre asignado a una zona privada que es asignada para una
sentencia SQL, esta rea contiene informacin acerca de la sentencia SQL y del rectngulo de
datos devueltos.
1.1 Cursores explcitos
a) Declaracin

CURSOR cemp IS
SELECT employee_id, job_id, salary
FROM employees
WHERE salary > 2000;

CURSOR cdep RETURN departments%ROWTYPE IS
SELECT * FROM departments ;

-- cursor con parametros
CURSOR c3 (p_department_id IN departments.department_id%TYPE ) IS
SELECT * FROM employees
WHERE department_id = p_department_id;

b) Apertura, consiste en abrir el cursor a travs de la sintaxis de la sentencia OPEN; Si la
consulta tiene una clusula FOR UPDATE, bloquea las filas del conjunto de resultados.
OPEN cemp;
c) Descarga, se lo realiza a travs de la sentencia FETCH y se necesita una estructura o
variables para descargar las columnas que contiene el select del cursor.
FETCH cemp INTO my_emp_id,my_job_id,my_sal ; --descarga
d) Cierre, es necesario para liberar recursos, cuando se desea que aplicaciones externas
accedan a datos del cursor es posible dejarlo abierto.
CLOSE cemp;
1.2 Atributos de cursores explcitos
Atributo Descripcin
%ISOPEN TRUE si el cursor est abierto.
FALSE si el cursor no est abierto
%FOUND INVALID_CURSOR cuando intenta evaluar y no se ha abierto
previamente.
NULL previo a la primera descarga.
TRUE si el registro ha sido descargado exitosamente.
FALSE si no hay registro que retornar
INVALID_CURSOR si el cursor ha sido cerrado.
%NOTFOUND INVALID_CURSOR cuando intenta evaluar y no se ha abierto.
NULL previo a la primera descarga..
FALSE si el registro ha sido descargado exitosamente.
TRUE si no hay registro que retornar.
INVALID_CURSOR si el cursor ha sido previamente cerrado.
%ROWCOUNT INVALID_CURSOR cuando intenta evaluar el atributo y no se ha
abierto previamente el cursor.
El nmero de registros descargados desde el cursor
INVALID_CURSOR si el cursor ha sido previamente cerrado.

Ejemplo de atributos de cursor
DECLARE
l_total INTEGER := 10000;

CURSOR employee_id_cur
IS
SELECT employee_id
FROM employees
ORDER BY salary ASC;

l_employee_id employee_id_cur%ROWTYPE;
BEGIN
OPEN employee_id_cur;

LOOP
FETCH employee_id_cur INTO l_employee_id;
EXIT WHEN employee_id_cur%NOTFOUND;
-- assign_bonus (l_employee_id, l_total);
EXIT WHEN l_total <= 0;
END LOOP;
DBMS_OUTPUT.Put_Line( 'Registros Procesados:
'||employee_id_cur%ROWCOUNT );
CLOSE employee_id_cur;
END;
1.3 Cursores Implcitos
Cuando se ejecutan sentencias SQL en nuestro cdigo PL/SQL estamos trabajando con cursores
implcitos. Las sentencias incluidas son INSERT, UPDATE, DELETE, SELECT INTO. A diferencia de los
explcitos estos cursores no necesitan ser abiertos, descargados ni cerrados. La sentencia SELCT
INTO maneja dos atributos de cursor que difieren de los cursores explicitos. Cuando un SELECT
INTO no retorna registros se produce la excepcin y el control se pasa a la seccin de excepcin.
Cuando una sentencia retorna ms de un registros se produce la excepcin TOO_MANY_ROWS y
el control es pasado a la seccin de excepciones. Se referencian de la siguiente forma:
DECLARE
l_last_name employees.last_name%TYPE;
BEGIN
SELECT last_name
INTO l_last_name
FROM employees
WHERE employee_id = 138;

DBMS_OUTPUT.put_line ( 'El apellido es: '|| l_last_name);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.Put_Line( 'No se encontraron registros' );

END;
Atributos en cursores implcitos
BEGIN
UPDATE employees SET salary = salary*1.10
WHERE employee_id = 100;

IF SQL%NOTFOUND THEN
DBMS_OUTPUT.Put_Line( 'No se han modificado registros' );
ELSE
DBMS_OUTPUT.Put_Line( SQL%ROWCOUNT ||' registros modicados' );
END IF;
ROLLBACK;
END;

1.4 Variables de cursor
Las variables de cursor se usan para el proceso de consultas que devuelven mltiples registros, a
diferencia de los cursores normales el rea de trabajo no tiene un nombre, y la variable es una
referencia a esta rea.
La sintaxis es la siguiente:

Los pasos a seguir son:
a) Declaracin de la variable de cursor
DECLARE
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE; -- strong type
TYPE genericcurtyp IS REF CURSOR; -- weak type

cursor1 empcurtyp; -- strong cursor variable
cursor2 genericcurtyp; -- weak cursor variable
my_cursor SYS_REFCURSOR; -- weak cursor variable

TYPE deptcurtyp IS REF CURSOR RETURN departments%ROWTYPE; -- strong
type
dept_cv deptcurtyp; -- strong cursor variable
BEGIN
NULL;
END;


En este ejemplo creamos un tipo personalizado para contener a la variable de cursor:

DECLARE
TYPE EmpRecTyp IS RECORD (
employee_id NUMBER,
last_name VARCHAR2(25),
salary NUMBER(8,2));

TYPE EmpCurTyp IS REF CURSOR RETURN EmpRecTyp;
emp_cv EmpCurTyp;
BEGIN
NULL;
END;
/




b) Apertura de la variable de cursor, consiste en abrir el cursor a travs de la sintaxis de la
sentencia OPEN;
OPEN emp_cv FOR ;
Asocia la variable de cursor con una consulta (por lo general, la consulta devuelve varias filas)
La consulta se puede incluir variables bind, que se enlazan al cursor los valores se especifica en
la clusula USING de la sentencia OPEN FOR.
Asigna los recursos de base de datos para procesar la consulta, es decir: Identifica el conjunto
de resultados. Si la consulta tiene una clusula FOR UPDATE, bloquea las filas del conjunto de
resultados
DECLARE
cv SYS_REFCURSOR; -- cursor variable
v_lastname employees.last_name%TYPE; -- variable for last_name
v_jobid employees.job_id%TYPE; -- variable for job_id
query_2 VARCHAR2(200) :=
'SELECT * FROM employees
WHERE REGEXP_LIKE (job_id, ''[ACADFIMKSA]_M[ANGR]'')
ORDER BY job_id';
v_employees employees%ROWTYPE; -- record variable row of TABLE
BEGIN
OPEN cv FOR
SELECT last_name, job_id FROM employees
WHERE REGEXP_LIKE (job_id, 'S[HT]_CLERK')
ORDER BY last_name;
LOOP -- Fetches 2 columns into variables
FETCH cv INTO v_lastname, v_jobid;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( RPAD(v_lastname, 25, ' ') || v_jobid );
END LOOP;
DBMS_OUTPUT.PUT_LINE( '-------------------------------------' );
OPEN cv FOR query_2;
LOOP -- Fetches entire row into the v_employees record
FETCH cv INTO v_employees;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( RPAD(v_employees.last_name, 25, ' ') ||
v_employees.job_id );
END LOOP;
CLOSE cv;
END;
/

c) Descarga, en este punto podemos proceder como se lo realiza en los cursores explcitos,
se lo realiza a travs de la sentencia FETCH y se necesita una estructura o variables para
descargar las columnas que contiene el select del cursor.
FETCH cemp INTO [var1,var2,..][estructura] ; --descarga
DECLARE
sal employees.salary%TYPE;
sal_multiple employees.salary%TYPE;
factor INTEGER := 2;
cv SYS_REFCURSOR;
BEGIN
OPEN cv FOR
SELECT salary, salary*factor
FROM employees
WHERE job_id LIKE 'AD_%'; -- PL/SQL evaluates factor

LOOP
FETCH cv INTO sal, sal_multiple;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('factor = ' || factor);
DBMS_OUTPUT.PUT_LINE('sal = ' || sal);
DBMS_OUTPUT.PUT_LINE('sal_multiple = ' || sal_multiple);
factor := factor + 1; -- Does not affect sal_multiple
END LOOP;
CLOSE cv;
END;
/

d) Cierre, es necesario para liberar recursos
CLOSE cemp;

2 Procedimientos almacenados
2.1 Paquetes

Los paquetes son objetos que residen en la base de datos, y sirven para organizar de manera
lgica las funciones y o procedimientos.
Tienen dos partes: La especificacin y el cuerpo.
La especificacin son los procedimientos o funciones pblicas visibles para otros paquetes, tanto a
nivel de oracle como de aplicaciones externas.



CREATE OR REPLACE PACKAGE emp_mgmt AS
FUNCTION hire (last_name VARCHAR2, job_id VARCHAR2,
manager_id NUMBER, salary NUMBER,
commission_pct NUMBER, department_id NUMBER)
RETURN NUMBER;
FUNCTION create_dept(department_id NUMBER, location_id NUMBER)
RETURN NUMBER;
PROCEDURE remove_emp(employee_id NUMBER);
PROCEDURE remove_dept(department_id NUMBER);
PROCEDURE increase_sal(employee_id NUMBER, salary_incr NUMBER);
PROCEDURE increase_comm(employee_id NUMBER, comm_incr NUMBER);
no_comm EXCEPTION;
no_sal EXCEPTION;
END emp_mgmt;
/



En el cuerpo o body est el texto completo de los procedimientos y/o funciones.


CREATE OR REPLACE PACKAGE BODY emp_mgmt AS
tot_emps NUMBER;
tot_depts NUMBER;
FUNCTION hire
(last_name VARCHAR2, job_id VARCHAR2,
manager_id NUMBER, salary NUMBER,
commission_pct NUMBER, department_id NUMBER)
RETURN NUMBER IS new_empno NUMBER;
BEGIN
SELECT employees_seq.NEXTVAL
INTO new_empno
FROM DUAL;
INSERT INTO employees
VALUES (new_empno, 'First', 'Last','first.example@oracle.com',
'(415)555-0100','18-JUN-02','IT_PROG',90000000,00,
100,110);
tot_emps := tot_emps + 1;
RETURN(new_empno);
END;
FUNCTION create_dept(department_id NUMBER, location_id NUMBER)
RETURN NUMBER IS
new_deptno NUMBER;
BEGIN
SELECT departments_seq.NEXTVAL
INTO new_deptno
FROM dual;
INSERT INTO departments
VALUES (new_deptno, 'department name', 100, 1700);
tot_depts := tot_depts + 1;
RETURN(new_deptno);
END;
PROCEDURE remove_emp (employee_id NUMBER) IS
BEGIN
DELETE FROM employees
WHERE employees.employee_id = remove_emp.employee_id;
tot_emps := tot_emps - 1;
END;
PROCEDURE remove_dept(department_id NUMBER) IS
BEGIN
DELETE FROM departments
WHERE departments.department_id = remove_dept.department_id;
tot_depts := tot_depts - 1;
SELECT COUNT(*) INTO tot_emps FROM employees;
END;
PROCEDURE increase_sal(employee_id NUMBER, salary_incr NUMBER) IS
curr_sal NUMBER;
BEGIN
SELECT salary INTO curr_sal FROM employees
WHERE employees.employee_id = increase_sal.employee_id;
IF curr_sal IS NULL
THEN RAISE no_sal;
ELSE
UPDATE employees
SET salary = salary + salary_incr
WHERE employee_id = employee_id;
END IF;
END;
PROCEDURE increase_comm(employee_id NUMBER, comm_incr NUMBER) IS
curr_comm NUMBER;
BEGIN
SELECT commission_pct
INTO curr_comm
FROM employees
WHERE employees.employee_id = increase_comm.employee_id;
IF curr_comm IS NULL
THEN RAISE no_comm;
ELSE
UPDATE employees
SET commission_pct = commission_pct + comm_incr;
END IF;
END;
END emp_mgmt;
/

Funciones
Procedimientos

Вам также может понравиться