CURSORES, EXCEPCIONES Y CONTROL DE TRANSACCIONES EN PL/SQL .........................
2
CURSORES .............................................................................................................................................2
Cursores implícitos...............................................................................................................................2
Cursores explícitos ...............................................................................................................................2
Atributos de los cursores ......................................................................................................................3
Variables de acoplamiento ...................................................................................................................4
Cursor FOR...LOOP.............................................................................................................................4
Cursores con parámetros .....................................................................................................................5
El cursor SQL.......................................................................................................................................6
Cursores para actualizar y borrar filas................................................................................................6
EXCEPCIONES.......................................................................................................................................8
Definición de la excepción ...................................................................................................................9
Lanzamiento de la excepción................................................................................................................9
Tratamiento de la excepción.................................................................................................................9
Propagación y ámbito de las excepciones..........................................................................................10
CONTROL DE TRANSACCIONES .....................................................................................................11
Transacción ........................................................................................................................................11
TRANSACCIONES Y CONTROL DE CONCURRENCIA.................................................................14
BIBLIOGRAFÍA ......................................................................................................................................14
CURSORES, EXCEPCIONES Y CONTROL DE TRANSACCIONES
EN PL/SQL
CURSORES
En general los cursores se utilizan para guardar los datos de una consulta. Dependiendo
de número de filas devueltas por la consulta se distinguen los siguientes tipos de
cursores:
Cursores implícitos
• Hay que declararlos previamente a su uso
• Sólo contendrán un valor devuelto por la consulta
• Si la consulta devuelve más de una fila se produce un error
EJEMPLO
DECLARE
v_ape VARCHAR(10);
v_oficio VARCHAR(10);
BEGIN
SELECT apellido, oficio INTO v_ape, v_oficio
FROM EMPLE
WHERE emp_no=7900;
DBMS_OUTPUT.PUT_LINE(v_ape || v_oficio);
END;
Cursores explícitos
Se emplean para recuperar los datos de una consulta que puede devolver más de una
fila. Para poder usarlos hay que realizar los 4 pasos siguientes:
1.- Declaración
Se hace en la zona DECLARE o IS/AS del bloque de la siguiente forma:
CURSOR <nombre_cursor> IS <sentencia_select>
En la zona BEGIN...END :
2.- Apertura del cursor que ejecuta la sentencia SELECT y llena el cursor con los datos
o filas
OPEN <nombre_cursor>
3.- Recogida de los datos de una fila y avance automático a la fila siguiente
FETCH <nombre_cursor> INTO {<variable>|<lista_variables>}
Cursores y excepciones 2
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
<lista_variables> debe corresponderse con las columnas devueltas por la
consulta SELECT del cursor.
Un cursor actúa como un puntero que apunta siempre a una fila de las seleccionadas con
la cláusula SELECT, dicha fila es la que se obtiene con la cláusula FETCH.
4.- Cierre del cursor cuando ya no se precise:
CLOSE <nombre_cursor>
EJEMPLO
DECLARE
CURSOR cur1 IS
SELECT dnombre, loc FROM depart;
v_nombre VARCHAR2(14);
v_localidad VARCHAR2(14);
BEGIN
OPEN cur1;
LOOP
FETCH cur1 INTO v_nombre, v_localidad;
EXIT WHEN cur1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_nombre||’*’||v_localidad);
END LOOP;
CLOSE cur1;
END;
Atributos de los cursores
Nos permiten conocer los detalles de la situación de un cursor. Se accede a ellos
mediante la siguiente forma:
<nombre_cursor><atributo>
donde <atributo> puede ser
ATRIBUTO USO
%FOUND Da verdadero (true) si el último FETCH
recuperó algún valor y falso en caso contrario.
Si el cursor no está abierto da error y NULL si
está abierto y no se ha ejecutado aún ningún
FETCH.
%NOTFOUND Lo contrario de %FOUND
%ROWCOUNT Devuelve el número de filas recuperadas con
FETCH
%ISOPEN Devuelve verdadero si el cursor está abierto
Cursores y excepciones 3
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
EJERCICIO
Realizar un bloque PL/SQL que muestre el contenido de la tabla ENVIOS utilizando un
cursor explícito.
Variables de acoplamiento
Son variables que se sustituyen por un valor cuando se abre el cursor permitiendo
parametrizar y definir de forma más abierta los cursores.
EJEMPLO
CREATE OR REPLACE PROCEDURE ver_emple_por_depto (
dep VARCHAR2)
AS
v_dept NUMBER(2);
CURSOR c1 IS
SELECT apellido FROM emple WHERE dep_no=v_dept;
v_apellido VARCHAR2(10);
BEGIN
V_dept:=dep;
OPEN c1;
FETCH c1 INTO v_apellido;
WHILE c1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(v_apellido);
FETCH c1 INTO v_apellido;
END LOOP;
CLOSE c1;
END;
Cursor FOR...LOOP
Es un cursor que solo precisa su declaración para ser usado. Este tipo de cursor es el que
normalmente se usa en PL/SQL. Para usarlo hay que realizar dos pasos:
• Declaración en la zona correspondiente (DECLARE o IS/AS)
CURSOR <nombre_cursor> IS <sentencia_select>
• Procesamiento mediante un bucle FOR
FOR nombre_variable_de_registro IN nombre_cursor LOOP
instrucciones;
END LOOP;
Con esto se realiza :
1. Al entrar en el bucle se abre el cursor de forma automática
2. Se declara implícitamente nombre_variable_de_registro de tipo
nombre_cursor%ROWTYPE.
Cursores y excepciones 4
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
3. Se ejecuta el primer FETCH cuyo resultado pasa a
nombre_variable_de_registro.
4. Se repite el paso 3 hasta que no queden más registros o filas en el cursor.
EJEMPLO
DECLARE
CURSOR mi_cursor IS
SELECT apellido, oficio, comision
FROM emple
WHERE COMISION > 50000;
BEGIN
FOR v_reg IN mi_cursor LOOP
DBMS_OUTPUT.PUT_LINE(v_reg.apellido||”*”||v_reg.oficio
||”*”||TO_CHAR((v_reg.comision, “999,999”));
END LOOP;
END;
Cursores con parámetros
Permiten pasar información al cursor cuando este se abre.
1.- Declaración
CURSOR nombre_cursor [(p1,p2,…)] IS
<sentencia_SELECT_con_parametros>;
Donde cada Pi (parámetro formal) se declara
Pi [IN] <tipodato> [{:=|DEFAULT} valor]
Todos los Pi son parámetros de entrada y su ámbito es local al cursor.
2.- Apertura pasándole argumentos
OPEN nombre_cursor [(arg1,arg2,…)];
EJEMPLO
DECLARE
v_dep emple.dept_no%TYPE;
v_ofi emple.oficio&TYPE;
CURSOR cur1 (v_departamento NUMBER,
v_oficio VARCHAR2 DEFAULT ‘DIRECTOR’)
IS SELECT apellido,salario FROM emple
WHERE dept_no=v_departamento AND oficio=v_oficio;
…
Cualquiera de estas tres aperturas es válida:
Cursores y excepciones 5
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
OPEN cur1(v_dep);
OPEN cur1(v_dep,v_ofi);
OPEN cur1(20,’vendedor’);
El cursor SQL
Es un cursor implícito que Oracle abre siempre que se ejecuta una sentencia SELECT
INTO, INSERT, UPDATE y DELETE. Este cursor tiene los mismos atributos que los
ya vistos.
SQL%FOUND VERDADERO si el último SELECT INTO, INSERT,
UPDATE o DELETE han afectado a una o más filas
SQL%NOTFOUND VERDADERO si el último SELECT INTO, INSERT,
UPDATE o DELETE no han afectado a ninguna.
SQL%ROWCOUNT Número de filas afectadas por el último SELECT INTO,
INSERT, UPDATE o DELETE.
SQL%ISOPEN FALSO siempre ya que Oracle cierra el cursor cuando termina
la ejecución de la sentencia.
EJEMPLO
…
UPDADTE depart SET loc=’SEVILLA’
WHERE dnombre=v_depto;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE(‘Error en la actualización’);
END IF;
…
Cursores para actualizar y borrar filas
Las filas seleccionadas por un cursor cuando se abre pueden borrarse de la tabla o
actualizarse. Para ello es necesario añadir la clausula FOR UPDATE en la declaración
del cursor:
• Declaración
CURSOR <nombre_cursor> IS <sentencia_select> FOR UPDATE;
Cuando se abre el cursor todas las filas seleccionadas quedan bloqueadas en la tabla.
La <sentencia_select> puede hacer referencia a múltiples tablas cuyas filas
quedarán bloqueadas cuando se abra el cursor. Para bloquear unicamente las filas de una
sola tabla declarará el cursor indicando el nombre de una columna de esa tabla
mediante la clausula OF nombre_de_columna:
CURSOR <nombre_cursor> IS <sentencia_select> FOR UPDATE OF
nombre_de_columna;
• Actualización/borrado
Cursores y excepciones 6
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
Para actualizar la fila actual del cursor escribiremos:
{UPDATE|DELETE}…WHERE CURRENT OF <nombre_cursor>
Donde
WHERE CURRENT OF <nombre_cursor> (del actual cusor) indica que se borre
o actualice la fila actual del cursor , la obtenida con el último FETCH
<nombre_cursor>
EJEMPLO
CREATE OR REPLACE PROCEDURE subir_salario_depto(vp_num_dpto
NUMBER, vp_pot_subida NUMBER)
AS
CURSOR c_emple IS SELECT oficio,salario
FROM emple
WHERE dept_no=vp_num_dpto
FOR UPDATE;
vc_reg_emple c_emple%ROWTYPE
v_inc NUMBER(8,2);
BEGIN
OPEN c_emple;
FETCH c_emple INTO vc_reg_emple;
WHILE c_emple%FOUND LOOP
V_inc:=( vc_reg_emple.salario/100)*vp_pot_subida;
UPDATE emple SET salario=salario+v_inc
WHERE CURRENT OF c_emple;
FETCH c_emple INTO vc_reg_emple;
END LOOP;
END subir_salario_depto;
Problemas de la clcláusula FOR UPDATE:
1. Se bloquean todas las filas seleccionadas por la sentencia SELECT en lugar de
la que actualmente apunta el cursor (con FETCH) que es la que se quiere
actualizar o borrar.
2. Si se ejecuta COMMIT ya no puede ejecutarse FETCH, puesto que el cursor se
cierra.
Para evitar el primer problema antes mencionado se usa un cursor normal cuya clausula
SELECT selecciona el identificador de fila ROWID:
CURSOR IS SELECT col1,col2,…,ROWID FROM tabla;
y para para actualizar o borrar una fila bloqueando sólo esa fila se escribe:
{UPDATE|DELETE}…WHERE ROWID=variable_que_guarda_rowid
Cursores y excepciones 7
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
EJEMPLO
CREATE OR REPLACE PROCEDURE subir_salario_depto(vp_num_dpto
NUMBER, vp_pot_subida NUMBER)
AS
CURSOR c_emple IS SELECT oficio,salario,ROWID
FROM emple
WHERE dept_no=vp_num_dpto;
vc_reg_emple c_emple%ROWTYPE
v_inc NUMBER(8,2);
BEGIN
OPEN c_emple;
FETCH c_emple INTO vc_reg_emple;
WHILE c_emple%FOUND LOOP
V_inc:=( vc_reg_emple.salario/100)*vp_pot_subida;
UPDATE emple SET salario=salario+v_inc
WHERE ROWID= vc_reg_emple.ROWID;
FETCH c_emple INTO vc_reg_emple;
END LOOP;
END subir_salario_depto;
EXCEPCIONES
Cuando en un programa se produce un error inesperado tenemos dos posibilidades de
actuación. Una opción es dejar que el programa termine directamente para que el
sistema operativo tome el control y resuelva el problema a su manera. Otra posibilidad
es intentar que el programa por si mismo maneje dicho error, es decir escribir código en
el propio programa para manejar el error. El lenguaje PL/SQL está preparado para esta
segunda opción que técnicamente se conoce como modelo de finalización mediante
manejo de excepciones. Este modelo es un estándar propuesto por la ANSI/ISO que se
basa en tres conceptos fundamentales: excepción, lanzamiento o levantamiento de una
excepción y manejador de excepción.
• Excepción: es una anomalía o error inesperado que se produce en tiempo de
ejecución de un programa.
• Lanzamiento de una excepción: consiste en pasar el control a otra parte del
programa encargada de manejar la excepción. El control se pasa en el punto o lugar
del código donde se ha producido la excepción y se puede pasar información a
través de argumentos que identifiquen la excepción ocurrida. Esto significa que debe
haber definidos o declarados unos parámetros (nombres de excepción) que
identifican a la excepción. Por lo tanto las excepciones en un programa se declaran
como cualquier otro tipo de dato.
• Manejador de excepción: es una parte o bloque de código encargado de
procesar una excepción. Cada excepción debe tener su manejador correspondiente.
Para trabajar con las excepciones es preciso:
1. Definir o declarar la excepción
Cursores y excepciones 8
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
2. Levantar o lanzar la excepción
3. Tratar la excepción con el correspondiente manejador
Definición de la excepción
Se distinguen en PL/SQL dos tipos de excepciones:
• Internas: no hay que definirlas pues ya están predefinidas por Oracle y se lanzan
automáticamente al producirse determinados errores identificados mediante el
nombre de la excepción.
• Definidas por el usuario se declaran en la zona DECLARE de la siguiente
forma:
nombre_de_excepcion EXCEPTION;
donde EXCEPTION indica un tipo de dato excepcion
Lanzamiento de la excepción
• Las excepciones internas se lanzan automáticamente cuando ocurre su suceso
asociado pasando el control y el nombre de la excepción de forma automática a
la sección de excepciones (EXCEPTION).
• Las excepciones definidas por el usuario hay que lanzarlas en el punto del
código (dentro de la sección ejecutable de un bloque) donde ocurre el error de la
siguiente manera:
RAISE nombre_de_excepcion;
Tratamiento de la excepción
En PL/SQL la zona de código encargada de manejar las excepciones tanto internas
como definidas por el usuario es la sección opcional de excepciones que tiene el
siguiente formato:
EXCEPTION
WHEN <nombre_excepcion1> THEN
instrucciones;
WHEN <nombre_excepcion2> THEN manejadores de excepción
instrucciones;
…
[WHEN OTHERS THEN
instrucciones;]
END nombre_del_programa;
Donde
Cursores y excepciones 9
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
nombre_excepcion1, nombre_excepcion2 son nombres de excepciones
internas o excepciones definidas por el usuario.
EJEMPLO
PROCEDURE subir_salario(num_empleado INTEGER, incremento
REAL)
IS
salario_actual REAL;
salario_nulo EXCEPTION;
BEGIN
SELECT salario INTO salario_Actual FROM emple
WHERE emp_no=num_empleado;
IF salario_actual IS NULL THEN
RAISE salario_nulo;
ELSE
UPDATE emple SET salario=salario+incremento
WHERE emp_no=num_empleado;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(num_emple||’*Error.No
encontrado’);
WHEN salario_nulo THEN
DBMS_OUTPUT.PUT_LINE(num_emple||’*Error.Salario
nulo’);
END subir_salario;
Propagación y ámbito de las excepciones
1.- Cuando se levanta o lanza la excepción el programa bifurca a la sección
EXCEPTION del bloque actual. Si no está el correspondiente manejador, la excepción
se propaga a la sección EXCEPTION del bloque que llamó al actual y así hasta que se
encuentre el manejador de excepción y si no se devuelve el control al programa host
que llamó al bloque PL/SQL.
2.-Tratada la excepción el control se devuelve al bloque que trató la excepción y no al
que la lanzó.
3.- Para devolver el control a la línea siguiente a la que produjo la excepción hay que
encerrar la instrucción que pueda producir el error y su manejador (sección
EXCEPTION) dentro de un bloque BEGIN…END:
Cursores y excepciones 10
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
BEGIN
…
BEGIN
Instrucción_que_ puede_ producir_ error;
EXCEPTION
WHEN NO_DATA_FOUND THEN
…
END;
instrucción_siguiente_a_la_del_error;
…
END;
4.- Si una excepción se levanta en la sección declarativa (DECLARE) se propagará al
bloque que llamó al actual sin comprobar si existe el manejador en el bloque actual e
igual si se levanta en la sección EXCEPTION.
5.- Para que una excepción, después de su tratamiento se propague al bloque de nivel
superior hay que volver a levantarla inmediatamente después de tratarla.
6.- Si la excepción se ha levantado dentro de un cursor FOR…LOOP entonces la
sección de excepciones no puede acceder a los atributos del cursor ya que Oracle cierra
el cursor al producirse la excepción.
RAISE_APPLICATION_ERROR
Es un procedimiento que se utiliza para lanzar excepciones de forma que los cambios
realizados por el subprograma o bloque PL/SQL antes de llamar a
RAISE_APPLICATION_ERROR se deshacen. LA sintaxis es la siguiente:
RAISE_APPLICATION_ERROR(num_error,mensaje_error);
Donde
-20000 <= num_eerror<=20999.
CONTROL DE TRANSACCIONES
Transacción
Conjunto de operaciones o instrucciones sobre una base de datos con la propiedad de
que se realizan todas o no se realiza ninguna. Una transacción constituye una unidad
lógica de trabajo.
PL/SQL permite que el usuario/programador defina el conjunto de instrucciones que
componen una transacción.
Antes de transacción o al comienzo de la transacción ⇒ hay un ESTADO en la base de
datos.
Fin de la transacción ⇒ la base de datos queda en un ESTADO diferente.
Las transacciones tienen como objetivo el poder restituir la base de datos a un estado
anterior a la transacción si ésta falla.
Cursores y excepciones 11
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
Una transacción comienza
• Con la primera orden SQL de la sesión del usuario.
• Con la primera orden SQL posterior a la finalización de la transacción anterior.
Una transacción finaliza
• Cuando se ejecutan los comandos COMMIT o ROLLBACK
• Con una orden DDL
• Cuando finaliza la sesión del usario ⇒ si no se pone COMMIT los cambios en la
base de datos no se hacen definitivos hasta que se acabe la sesión.
Comandos de control de transacciones
COMMIT Señala el término exitoso de una
transacción. Concluye la transacción
actual y hace definitivos los cambios
liberando las filas bloqueadas. Siempre
se ejecuta automáticamente al cerrar la
sesión. Después de ejecutar COMMIT
los demás usuarios tendrán acceso a los
datso modificados.
ROLLBACK Señala el término no exitoso de la
transacción. Da por concluida la
transacción actual y deshace los
cambios que se pudiesen haber
producido en la misma restaurando la
base de datos al estado anterior a la
transacción. Cuando un subprograma
almecenado falla y no se controla la
excepción que produjo el fallo Oracle
realiza un ROLLBACK sobre las
acciones del subprograma.
ROLLBACK <punto de salvaguarda> Deshace el trabajo que se realiza
después o a partir del <punto de
salvaguarda>
SAVEPOINT <punto de salvaguarda> Marca un punto de salvaguarda
SET TRASACTION READ ONLY Establece el comienzo de una
transacción de sólo lectura. Todas las
consultas ejecutadas a continuación sólo
verán aquellos cambios confirmados
antes del comienzo de la transacción.
Cursores y excepciones 12
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
EJEMPLOS
1.- Supongamos que la tabla de piezas tiene un nuevo campo, cant_total, que
indica para cada pieza el número de ejemplares que se han suministrado hasta el
momento. Esto hace que al insertar un envío en la tabla de envíos tengamos que
incrementar la cantidad total de la pieza involucrada, es decir las dos operaciones de
inserción y actualización se sonsideran una unidad o se realizan las dos o ninguna,
constituyendo una transación.
BEGIN
INSERT
INTO ENVÍOS(S#,P#,J#,CANTIDAD)
VALUES(‘S5’,P1’,’J2’,1000);
UPDATE PIEZAS
SET CANT_TOTAL=CANT_TOTAL+1000
WHERE P#=’P1’;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(”No se ha introducido el envío”);
ROLLBACK;
END;
Cuando ocurre una excepción PL/SQL pasa el control al bloque de excepciones donde
se ordena que se deshaga la transacción. Si no ocurre error explícitamante obligamos
con COMMIT que termine la transacción y los cambios se hagan efectivos, es decir
pasen del buffer a la base de datos.
2.-
CREATE OR REPLACE PROCEDURE prueba_savepoint (numfilas
POSITIVE)
AS
BEGIN
SAVEPONT NINGUNA;
INSERT INTO temp1 (col1) VALUES (‘PRIMERA FILA’);
SAVEPONT UNA;
INSERT INTO temp1 (col1) VALUES (‘SEGUNDA FILA’);
SAVEPOINT DOS;
IF numfilas=1 THEN
ROLLBACK TO UNA;
ELSE IF numfilas=2 THEN
ROLLBACK TO DOS;
ELSE
ROLLBACK TO NINGUNA;
END IF;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
Cursores y excepciones 13
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006
TRANSACCIONES Y CONTROL DE CONCURRENCIA
Bibliografía
Mª.Jesús Ramos, Alicia Ramos, Fernando Montero. “Desarrollo de aplicaciones en
entornos de 4ªgeneración y con herramientas case”. Ed. McGraw-Hill (2000)
Cursores y excepciones 14
Jesús Pedro Romero Castellano-IES P.Jimenez Montoya-2006