Está en la página 1de 9

Oracle/PL/SQL/Cursores

< Oracle | PL/SQL


Los cursores permiten recorrer los registros que devuelve una consulta SQL.
Tambin las operaciones INSERT, UPDATE Y DELETE definen un cursor implcito,
denominado SQL.
Atributos de un cursor:

%ROWCOUNT: Cantidad de registros

%FOUND: Indica que hay datos (tipo boolean)

%NOTFOUND: Indica que no hay datos (tipo boolean)

%ISOPEN: Indica si el cursor est abierto (tipo boolean)

Ciclo FOR
declare
cursor public cur is
select col1, col2
from tabla;
begin
for v_reg in cur loop
dbms_output.put_line ('Col1: '|| v_reg.col1 ||'
v_reg.col2);
end loop;
end;

Col2: '||

La variable v_reg se declara automticamente y tiene validez nicamente dentro del ciclo
FOR.
Es posible definir argumentos al declarar un cursor:
declare
cursor cur (p_col3 col3%type) is
select col1, col2
from tabla
where col3 = p_col3;
v_col3 tabla.col3%type;
begin
v_col3 := 7;

for v_reg in cur (v_col3) loop


dbms_output.put_line ('Col1: '|| v_reg.col1 ||'
v_reg.col2);
end loop;
end;

Col2: '||

OPEN, FETCH y CLOSE


En ciertos casos, es necesario realizar el procesamiento del cursor paso a paso:
declare
cursor cur is
select col1, col2
from tabla;
v_reg cur%rowtype;
begin
open cur;
loop
fetch cur into v_reg;
exit when cur%notfound;
dbms_output.put_line ('Col1: '|| v_reg.col1 ||'
v_reg.col2);
end loop;
close cur;
end;

Col2: '||

REF CURSOR
Tambin se pueden definir cursores variables, a diferencia de los estticos utilizados hasta
ahora:
declare
type t_cursor is ref cursor return tabla%rowtype;
v_cursor t_cursor;
v_reg tabla%rowtype;
begin
open v_cursor for
select col1, col2
from tabla;
loop
fetch v_cursor into v_reg;
exit when v_cursor%notfound;
dbms_output.put_line ('Col1: '|| v_reg.col1 ||'
v_reg.col2);
end loop;
close v_cursor;
end;

Col2: '||

Los cursores variables pueden ser pasados como parmetros en procedimientos y funciones.

Tambin es posible no especificar el tipo de registro retornado por el cursor, lo cual permite
mayor flexiblidad pero impide verificar los tipos en tiempo de compilacin, lo cual puede
dar lugar a errores imprevistos en tiempo de ejecucin.

Cursores de actualizacin
Declaracin y utiizacin de cursores de actualizacin.
Los cursores de actualizacin se declarn igual que los cursores explicitos, aadieno
FOR UPDATE al final de la sentencia select.
CURSOR nombre_cursor IS
instruccin_SELECT
FOR UPDATE

Para actualizar los datos del cursor hay que ejecutar una sentencia UPDATE
especificando la clausula WHERE CURRENT OF <cursor_name>.
UPDATE <nombre_tabla> SET
<campo_1> = <valor_1>
[,<campo_2> = <valor_2>]
WHERE CURRENT OF <cursor_name>

El siguiente ejemplo muestra el uso de un cursor de actualizacin:


DECLARE
CURSOR cpaises IS
select CO_PAIS, DESCRIPCION, CONTINENTE
from paises
FOR UPDATE;
co_pais VARCHAR2(3);
descripcion VARCHAR2(50);
continente VARCHAR2(25);
BEGIN
OPEN cpaises;
FETCH cpaises INTO co_pais,descripcion,continente;
WHILE cpaises%found
LOOP
UPDATE PAISES
SET CONTINENTE = CONTINENTE || '.'
WHERE CURRENT OF cpaises;
FETCH cpaises INTO co_pais,descripcion,continente;
END LOOP;
CLOSE cpaises;

COMMIT;
END;

Excepciones en PL/SQL
Manejo de excepciones
En PL/SQL una advertencia o condicin de error es llamada una excepcin.
Las excepciones se controlan dentro de su propio bloque.La estructura de bloque de una
excepcin se muestra a continuacin.
DECLARE
-- Declaraciones
BEGIN
-- Ejecucion
EXCEPTION
-- Excepcion
END;

Cuando ocurre un error, se ejecuta la porcin del programa marcada por el


bloque EXCEPTION, transfirindose el control a ese bloque de sentencias.
El siguiente ejemplo muestra un bloque de excepciones que captura las excepciones
NO_DATA_FOUND y ZERO_DIVIDE. Cualquier otra excepcion ser capturada en el
bloque WHEN OTHERS THEN.
DECLARE
-- Declaraciones
BEGIN
-- Ejecucion
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Se ejecuta cuando ocurre una excepcion de tipo NO_DATA_FOUND
WHEN ZERO_DIVIDE THEN
-- Se ejecuta cuando ocurre una excepcion de tipo ZERO_DIVIDE
WHEN OTHERS THEN
-- Se ejecuta cuando ocurre una excepcion de un tipo no tratado
-- en los bloques anteriores
END;

Como ya hemos dicho cuando ocurre un error, se ejecuta el bloque EXCEPTION,


transfirindose el control a las sentencias del bloque. Una vez finalizada la ejecucin del
bloque de EXCEPTION no se continua ejecutando el bloque anterior.
Si existe un bloque de excepcion apropiado para el tipo de excepcin se ejecuta dicho
bloque. Si no existe un bloque de control de excepciones adecuado al tipo de excepcion se
ejecutar el bloque de excepcion WHEN OTHERS THEN (si existe!). WHEN OTHERS
debe ser el ltimo manejador de excepciones.
Las excepciones pueden ser definidas en forma interna o explcitamente por el usuario.
Ejemplos de excepciones definidas en forma interna son la divisin por cero y la falta de
memoria en tiempo de ejecucin. Estas mismas condiciones excepcionales tienen sus
propio tipos y pueden ser referenciadas por ellos: ZERO_DIVIDE y
STORAGE_ERROR.
Las excepciones definidas por el usuario deben ser alcanzadas explcitamente utilizando
la sentencia RAISE.
Con las excepciones se pueden manejar los errores cmodamente sin necesidad de
mantener mltiples chequeos por cada sentencia escrita. Tambin provee claridad en el
cdigo ya que permite mantener las rutinas correspondientes al tratamiento de los
errores de forma separada de la lgica del negocio.
Excepciones predefinidas
PL/SQL proporciona un gran nmero de excepciones predefinidas que permiten
controlar las condiciones de error ms habituales.
Las excepciones predefinidas no necesitan ser declaradas. Simplemente se utilizan
cuando estas son lanzadas por algn error determinado.
La siguiente es la lista de las excepciones predeterminadas por PL/SQL y una breve
descripcin de cundo son accionadas:
Excepcion
ACCESS_INTO_NULL
COLLECTION_IS_NULL

CURSOR_ALREADY_OPEN

Se ejecuta ...

SQLCODE

El programa intent asignar valores a los


-6530
atributos de un objeto no inicializado
El programa intent asignar valores a
-6531
una tabla anidada an no inicializada
El programa intent abrir un cursor que
ya se encontraba abierto. Recuerde que
un cursor de ciclo FOR automticamente -6511
lo abre y ello no se debe especificar con
la sentencia OPEN

El programa intent almacenar valores


duplicados en una columna que se
DUP_VAL_ON_INDEX
-1
mantiene con restriccin de integridad
de un ndice nico (unique index)
El programa intent efectuar una
INVALID_CURSOR
-1001
operacin no vlida sobre un cursor
En una sentencia SQL, la conversin de
una cadena de caracteres hacia un
INVALID_NUMBER
-1722
nmero falla cuando esa cadena no
representa un nmero vlido
El programa intent conectarse a Oracle
LOGIN_DENIED
con un nombre de usuario o password -1017
invlido
Una sentencia SELECT INTO no
devolvi valores o el programa
NO_DATA_FOUND
100
referenci un elemento no inicializado
en una tabla indexada
El programa efectu una llamada a
NOT_LOGGED_ON
-1012
Oracle sin estar conectado
PROGRAM_ERROR
PL/SQL tiene un problema interno
-6501
Los elementos de una asignacin (el
valor a asignar y la variable que lo
contendr) tienen tipos incompatibles.
ROWTYPE_MISMATCH
-6504
Tambin se presenta este error cuando
un parmetro pasado a un subprograma
no es del tipo esperado
El parmetro SELF (el primero que es
SELF_IS_NULL
-30625
pasado a un mtodo MEMBER) es nulo
STORAGE_ERROR
La memoria se termin o est corrupta -6500
El programa est tratando de referenciar
un elemento de un arreglo indexado que
SUBSCRIPT_BEYOND_COUNT se encuentra en una posicin ms grande -6533
que el nmero real de elementos de la
coleccin
El programa est referenciando un
elemento de un arreglo utilizando un
SUBSCRIPT_OUTSIDE_LIMIT
-6532
nmero fuera del rango permitido (por
ejemplo, el elemento -1)
La conversin de una cadena de
caracteres hacia un tipo rowid fall
SYS_INVALID_ROWID
-1410
porque la cadena no representa un
nmero
Se excedi el tiempo mximo de espera
TIMEOUT_ON_RESOURCE
-51
por un recurso en Oracle
TOO_MANY_ROWS
Una sentencia SELECT INTO devuelve -1422

VALUE_ERROR

ZERO_DIVIDE

ms de una fila
Ocurri un error aritmtico, de
conversin o truncamiento. Por ejemplo,
sucede cuando se intenta calzar un valor -6502
muy grande dentro de una variable ms
pequea
El programa intent efectuar una
-1476
divisin por cero

Excepciones definidas por el usuario


PL/SQL permite al usuario definir sus propias excepciones, las que debern ser
declaradas y lanzadas explcitamente utilizando la sentencia RAISE.
Las excepciones deben ser declaradas en el segmento DECLARE de un bloque,
subprograma o paquete. Se declara una excepcin como cualquier otra variable,
asignandole el tipo EXCEPTION. Las mismas reglas de alcance aplican tanto sobre
variables como sobre las excepciones.

DECLARE
-- Declaraciones
MyExcepcion EXCEPTION;
BEGIN
-- Ejecucion
EXCEPTION
-- Excepcion
END;

Reglas de Alcance
Una excepcion es vlida dentro de su ambito de alcance, es decir el bloque o programa
donde ha sido declarada. Las excepciones predefinidas son siempre vlidas.
Como las variables, una excepcin declarada en un bloque es local a ese bloque y global
a todos los sub-bloques que comprende.
La sentencia RAISE
La sentencia RAISE permite lanzar una excepcin en forma explcita. Es posible utilizar
esta sentencia en cualquier lugar que se encuentre dentro del alcance de la excepcin.

DECLARE

-- Declaramos una excepcion identificada por VALOR_NEGATIVO


VALOR_NEGATIVO EXCEPTION;
valor NUMBER;
BEGIN
-- Ejecucion
valor := -1;
IF valor < 0 THEN
RAISE VALOR_NEGATIVO;
END IF;

EXCEPTION
-- Excepcion
WHEN VALOR_NEGATIVO THEN
dbms_output.put_line('El valor no puede ser negativo');
END;

Con la sentencia RAISE podemos lanzar una excepcin definida por el usuario o
predefinida, siendo el comportamiento habitual lanzar excepciones definidas por el usuario.
Recordar la existencia de la excepcin OTHERS, que simboliza cualquier condicin de
excepcin que no ha sido declarada. Se utiliza comnmente para controlar cualquier tipo de
error que no ha sido previsto. En ese caso, es comn observar la sentencia ROLLBACK en
el grupo de sentencias de la excepcin o alguna de las funciones SQLCODE
SQLERRM, que se detallan en el prximo punto.
Uso de SQLCODE y SQLERRM
Al manejar una excepcin es posible usar las funciones predefinidas SQLCode y
SQLERRM para aclarar al usuario la situacin de error acontecida.
SQLcode devuelve el nmero del error de Oracle y un 0 (cero) en caso de exito al
ejecutarse una sentencia SQL.
Por otra parte, SQLERRM devuelve el correspondiente mensaje de error.
Estas funciones son muy tiles cuando se utilizan en el bloque de excepciones, para
aclarar el significado de la excepcin OTHERS.

Estas funciones no pueden ser utilizadas directamente en una sentencia SQL, pero s se
puede asignar su valor a alguna variable de programa y luego usar esta ltima en alguna
sentencia.
DECLARE
err_num NUMBER;
err_msg VARCHAR2(255);
result NUMBER;
BEGIN
SELECT 1/0 INTO result
FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SQLERRM;
DBMS_OUTPUT.put_line('Error:'||TO_CHAR(err_num));
DBMS_OUTPUT.put_line(err_msg);
END;
Tambin es posible entregarle a la funcin SQLERRM un nmero negativo que represente un error de
Oracle y sta devolver el mensaje asociado.

DECLARE
msg VARCHAR2(255);
BEGIN
msg := SQLERRM(-1403);
DBMS_OUTPUT.put_line(MSG);
END;

También podría gustarte