Conf 3 Trigger y Cursores
Conf 3 Trigger y Cursores
Conf 3 Trigger y Cursores
Introducción
Desarrollo
TRIGGER
Se han visto las ventajas que la funciones proporcionan al simplificar acciones en una
base de datos. Pero estas acciones requieren la intervención de una persona
encargada de ejecutar las funciones cuando se requiera de su actuación. Los triggers
al contrario, son funciones que se ejecutan de forma automática en respuesta a ciertos
eventos que ocurren en la base de datos.
Un trigger es una acción en cadena que empieza cuando un evento específico ocurre
sobre una tabla específica.
Nota: TRUNCATE es un evento a través del cual se pueden eliminar todas las filas de
una tabla o de un conjunto de tablas.
Su sintaxis es la siguiente:
TRUNCATE [ TABLE ] [ ONLY ] name [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
Si se especifica ONLY solo la tabla indicada en el comando es truncada, sino serán
truncadas además las tablas descendientes (si las hay).
Si se especifica RESTART IDENTITY se reinician automáticamente los campos
secuenciales de la tabla truncada. Si se especifica CONTINUE IDENTITY no se
producen cambios en los valores de las secuencias, este es el valor por defecto.
Si se especifica CASCADE, serán truncadas además de la tabla indicada, todas
aquellas que hagan referencia a través de una llave foránea a algún campo de la tabla
especificada en el comando.
Si se especifica RESTRICT, la tabla indicada en el comando no será truncada mientras
exista alguna otra tabla que haga referencia a ella a través de una llave foránea. Esta
es la opción por defecto.
El uso de los triggers está muy vinculado con la realización de acciones para auditar y
monitorear la actividad de cambio de datos dentro de una base de datos. Permiten
validar datos, cambiando o negando acciones como INSERT, UPDATE y DELETE en
una tabla. Además, su funcionalidad les permite preservar la consistencia y claridad de
los datos ejecutando acciones relacionadas con otras tablas.
Ejemplo:
Argumentos:
nombre_trigger: Es el nombre del desencadenador.
FOR EACH [ROW | STATEMENT]: Para cada fila o para cada sentencia.
NEW: Variable compuesta que almacena los nuevos valores de la tupla que se está
modificando.
OLD: Variable compuesta que almacena los valores antiguos de la tupla que se está
modificando.
TG_OP: Variable tipo string que indica qué tipo de evento está ocurriendo (INSERT,
UPDATE, DELETE).
TG_ARGV: Variable tipo arreglo que almacena los parámetros de la función del trigger,
los cuales se pueden acceder de la forma TG_ARGV[0], TG_ARGV[1], …
TG_ARGV[n].
Entonces, ¿cuáles son las acciones que se deben realizar con un trigger?
Se necesita llevar un registro de todos los cambios relevantes en la tabla
PRODUCTO, comenzando por tener un seguimiento de los cambios en los
precios de los productos.
Se debe crear una tabla que almacene los cambios de precio en la tabla PRODUCTO,
la cual se llamará PRODUCTO_ACTUALIZADO.
Se debe tener en cuenta que los triggers a nivel de columna sólo se pueden aplicar a
las operaciones de tipo UPDATE, incluso si un trigger se dispara por más de un evento
estos deberán ser separados obligatoriamente. No tendría sentido usar INSERT en
este tipo de disparadores, ya que al ejecutar esta sentencia todas las columnas son
afectadas; así como en el caso del DELETE tampoco se utilizaría, ya que este se aplica
directamente sobre una fila y no sobre las columnas.
Condición: Es una expresión booleana que se tiene que verificar para que se ejecute
el trigger.
Ejemplo: En este ejemplo se resuelve la misma problemática del ejemplo anterior, pero
utilizando un trigger condicional.
CREATE TRIGGER disparador1 BEFORE UPDATE
ON producto
FOR EACH ROW
WHEN (OLD.nombre IS DISTINCT FROM NEW.nombre) EXECUTE PROCEDURE
mi_function();
CURSORES
Las operaciones de una base de datos relacional actúan en un conjunto completo de
filas. El conjunto de filas que devuelve una instrucción SELECT está compuesto por
todas las filas que satisfacen las condiciones de la cláusula WHERE de la instrucción.
Este conjunto completo de filas que devuelve la instrucción se conoce como el conjunto
de resultados. Las aplicaciones no siempre pueden trabajar de forma efectiva con el
conjunto de resultados completo si lo toman como una unidad. Estas aplicaciones
necesitan un mecanismo que trabaje con una fila o un pequeño bloque de filas cada
vez. Precisamente los cursores representan consultas SELECT de SQL que devuelven
más de un resultado y que permiten el acceso a cada fila de una consulta.
Declarar el Cursor
Sintaxis:
DECLARE
cursor_name CURSOR FOR select_statement;
Pueden definirse varios cursores en una rutina, pero cada cursor en un bloque debe
tener un nombre único.
Argumentos:
cursor_name: Especifica el nombre del cursor.
Ejemplo:
DECLARE
curs1 refcursor;
curs2 CURSOR FOR SELECT * FROM empleado;
Los dos cursores declarados anteriormente tienen el tipo de datos refcursor, pero el
primer cursor (curs1) puede ser usado para cualquier consulta, mientras que el
segundo es específico para la consulta SELECT * FROM empleado.
Comandos para el trabajo con cursores
OPEN cursor
Esta instrucción cuenta con una opción direction que indica la dirección del recorrido,
que puede ser: NEXT, PRIOR, FIRST, LAST, ABSOLUTE count, RELATIVE count,
FORWARD o BACKWARD. La omisión de esta cláusula implica que el gestor asuma
por defecto el valor NEXT para la misma.
FIRST: Selecciona la primera fila de la consulta (es lo mismo que: ABSOLUTE 1).
LAST: Selecciona la última fila de la consulta (es lo mismo que: ABSOLUTE -1).
RELATIVE count: Selecciona la n-ésima fila que sigue a la fila actual. Si count es
negativo se selecciona la n-ésima fila que precede a la fila actual. RELATIVE 0
selecciona la fila actual.
Ejemplos:
FETCH curs1 INTO rowvar;
FETCH curs2 INTO foo, bar, baz;
FETCH LAST FROM curs3 INTO x, y;
FETCH RELATIVE -2 FROM curs4 INTO x;
FETCH cursorProvincias INTO v_nombre, v_poblacion;
Una instrucción FETCH lee una sola fila y su contenido lo almacena en variables. Por
ello se requiere usar bucles cuando se quieren procesar un conjunto de filas de la
consulta asociada al cursor:
LOOP
FETCH cursorProvincias INTO (v_nombre, v_poblacion);
EXIT WHEN... --aquí se pondría la condición de salida...
--instrucciones de proceso de los datos del cursor
END LOOP;
Nota: Si sólo se quisieran mostrar los valores de la consulta asociada al cursor no hay
necesidad de utilizar la cláusula INTO.
Ejemplo:
FETCH ALL IN funccursor – Muestra todas las filas de la consulta asociada al cursor
funccursor.
CLOSE cursor
ALL: Selecciona todas las filas siguientes (es lo mismo que FORDWARD ALL).
Ejemplos:
MOVE curs1;
MOVE LAST FROM curs3;
MOVE RELATIVE -2 FROM curs4;
MOVE FORWARD 2 FROM curs4;
CURRENT OF
Cuando el cursor se posiciona en una fila de la tabla, la fila puede ser actualizada o
borrada. La sintaxis para ello es la siguiente:
Ejemplo:
cursorProvincias IS OPEN;
Ejemplo:
BEGIN
OPEN cursorProvincias;
LOOP
FETCH cursorProvincias INTO v_nombre,v_poblacion;
EXIT WHEN NOT FOUND;
END LOOP;
CLOSE cursorProvincias;
END;
Ejemplo:
DECLARE
cur_personas CURSOR (dep NUMBER, pue VARCHAR2 (20)) FOR
SELECT nombre, apellidos
FROM empleados
WHERE departamento=dep AND puesto=pue;
BEGIN
OPEN cur_personas (12,’administrativo’);
.....
CLOSE cur_personas;
END
Es al abrir el cursor cuando se indica el valor de los parámetros, lo que significa que se
puede abrir varias veces el cursor y que éste obtenga distintos resultados dependiendo
del valor del parámetro.
Utilización del ciclo FOR para iterar sobre los resultados de un cursor:
La conocida estructura repetitiva FOR, también puede ser utilizada para recorrer cada
uno de los resultados de la consulta a la que se encuentra asociado determinado
cursor. La sintaxis para ello es la que aparece a continuación:
Se hace necesario que se haya asociado una consulta al cursor cuando el mismo se
declaró. El FOR abre automáticamente el cursor y lo cierra cuando sale del bucle.
Ejemplo
DECLARE
cur_personas CURSOR (dep NUMBER, pue VARCHAR2 (20)) FOR
SELECT nombre, apellidos
FROM empleados
WHERE departamento=dep AND puesto=pue;
BEGIN
FOR r IN cur_personas (12,’administrativo’)
LOOP
.....
END LOOP;
END:
Cuando se necesita ejecutar una consulta que debe mostrar grandes volúmenes de
datos, es conveniente aplicar cursores en una de sus variantes más eficaces:
Implementar una función que devuelva una referencia a un cursor. Esta aplicación de
los cursores minimiza el tiempo de ejecución de las consultas para la obtención de
volúmenes de datos considerables.
Conclusiones
Hasta aquí se vieron los elementos básicos de dos contenidos muy importantes y de
amplia utilización en el trabajo con bases de datos: los triggers y los cursores.
El uso de los triggers y cursores pueden resultar muy útiles ante determinadas
necesidades de información o de comportamiento de una base de datos; pero un uso
desmedido de ambos trae consigo demora en la ejecución de las consultas y un gran
consumo de recurso por parte del servidor de base de datos.