Continuamos con los cursores, esta vez vamos a ver atributos con cursores explícitos y uso de cursores para actualizar filas.
Atributos con Cursores implícitos
Los atributos de los cursores implícitos que se crean son los siguientes:- SQL%NOTFOUND: nos dice si el último insert, update,delete o select into no han afectado a ninguna fila.
- SQL%FOUND: nos dice si el último insert, update,delete o select into ha afectado a una o mas filas
- SQL%ROWCOUNT: devuelve el número de filas afectadas por el último insert, update, delete o select into
- SQL%ISOPEN: Nos dice si el cursor esta cerrado, por lo que en teoría siempre nos dará falso ya que Oracle cierra automáticamente el cursor después de cada orden SQL.
Es importante tener en cuenta una serie de cosas:
Si se trata de un select into tenemos que tener en cuenta que solo puede devolver una única fila de lo contrario nos levantará automáticamente una de estas dos excepciones:
Cuando un select into hace referencia a una función de grupo nuca se levantará la excepción NO_DATA_FOUND y SQL%FOUND siempre será verdadero. Esto se explica porque las funciones de grupo siempre devuelven algún valor (NULL se considera un valor).
Uso de cursores para actualizar filas
Para realizar una actualización con un cursor tenemos que añadir la siguiente FOR UPDATE al final de la declaración del cursor:
CURSOR nombre_cursor <declaraciones> FOR UPDATE
Esto indica que las filas seleccionadas por el cursor van a ser actualizadas o borradas. Una vez declarado un cursor FOR UPDATE, se incluirá el especificador CURRENT OF nombre_cursor en la cláusula WHERE para actualizar o borrar la última fila recuperada mediante la orden FETCH.
{UPDATE|DELETE}... WHERE CURRENT OF nombre_cursor.
Os pongo un ejemplo para que quede claro:
Subir el salario a todos los empleados del departamento indicado en la llamada. El porcentaje se indicará también en la llamada.
CREATE OR REPLACE PROCEDURE subir_salario (num_dept NUMBER, incre NUMBER)
IS
CURSOR c IS SELECT oficio, salario FROM empleados WHERE cod_dept=num_dept
FOR UPDATE;
reg c%ROWTYPE;
inc NUMBER (8);
BEGIN
OPEN c;
FETCH c INTO reg;
WHILE c%FOUND LOOP
inc :=(reg.salario/100 )* inc;
UPDATE empleados SET salario=salario+inc WHERE CURRENT OF c
FETCH c INTO reg;
END LOOP;
END;
También podemos usar ROWID en lugar de FOR UPDATE. ROWID nos indicará la fila que se va a actualizar. Para ello, al declarar el cursor en la cláusula SELECT indicaremos que seleccione también el identificador de fila:
CURSOR nombre_cursor IS SELECT columna1,columna2,...ROWID FROM tabla;
Al ejecutarse el FETCH se guardará el número de fila en una variable y después ese número se podrá usar en la cláusula WHERE de la actualización:
{UPDATE |DELETE } ... WHERE ROWID = variable_rowid
El ejemplo anterior utilizando ROWID quedaría de la siguiente manera:
CREATE OR REPLACE PROCEDURE subir_salario (num_dept NUMBER, incre NUMBER)
IS
CURSOR c IS SELECT oficio, salario,ROWID FROM empleados WHERE cod_dept=num_dept
FOR UPDATE;
reg c%ROWTYPE;
inc NUMBER (8);
BEGIN
OPEN c;
FETCH c INTO reg;
WHILE c%FOUND LOOP
inc :=(reg.salario/100 )* inc;
UPDATE empleados SET salario=salario+inc WHERE ROWID = reg.ROWID;
FETCH c INTO reg;
END LOOP;
END;
Con este artículo damos por terminado todo lo referente a cursores y empezamos a tratar las excepciones en el siguiente artículo.