144 - Disparador de actualización (update trigger) |
Podemos crear un disparador para que se ejecute siempre que una instrucción "update" actualice los datos de una tabla.
Sintaxis básica:
create triggre NOMBREDISPARADOR on NOMBRETABLA for update as SENTENCIAS
Analizamos la sintaxis:
"create trigger" junto al nombre del disparador; "on" seguido del nombre de la tabla para la cual se establece el trigger.
Luego de "for" se coloca el evento (en este caso "update"), lo que indica que las actualizaciones sobre la tabla activarán el trigger.
Luego de "as" se especifican las condiciones y acciones, es decir, las condiciones que determinan cuando un intento de modificación provoca las acciones que el trigger realizará.
El siguiente disparador de actualización se crea para evitar que se modifiquen los datos de la tabla "libros":
create trigger DIS_libros_actualizar on libros for update as raiserror('Los datos de la tabla "libros" no pueden modificarse', 10, 1) rollback transaction
Entonces, creamos el disparador ("create trigger") dándole un nombre ("DI_libros_actualizar") sobre una tabla específica ("libros") para ("for") el suceso de actualización ("update"). Luego de "as" colocamos las sentencias, las acciones que el trigger realizará cuando se intente actualizar uno o varios registros en "libros" (en este caso, impedir las modificaciones).
Cuando se ejecuta una instrucción "update" en una tabla que tiene definido un disparador, los registros originales (antes de ser actualizados) se mueven a la tabla virtual "deleted" y los registros actualizados (con los nuevos valores) se copian a la tabla virtual "inserted". Dentro del trigger se puede acceder a estas tablas.
En el cuerpo de un trigger se puede emplear la función "update(campo)" que recibe un campo y retorna verdadero si el evento involucra actualizaciones (o inserciones) en ese campo; en caso contrario retorna "false".
Creamos un disparador que evite que se actualice el campo "precio" de la tabla "libros":
create trigger DIS_libros_actualizar_precio on libros for update as if update(precio) begin raiserror('El precio de un libro no puede modificarse.', 10, 1) rollback transaction end;
Empleamos "if update()" para que el trigger controle la actualización del campo "precio"; así, cuando el disparador detecte una actualización en tal campo, realizará las acciones apropiadas (mostrar un mensaje y deshacer la actualización); en caso que se actualice otro campo, el disparador se activa, pero permite la transacción.
Creamos un disparador de actualización que muestra el valor anterior y nuevo valor de los registros actualizados:
create trigger DIS_libros_actualizar2 on libros for update as if (update(titulo) or update(autor) or update(editorial)) and not (update(precio) or update(stock)) begin select d.codigo, (d.titulo+'-'+ d.autor+'-'+d.editorial) as 'registro anterior', (i.titulo+'-'+ i.autor+'-'+i.editorial) as 'registro actualizado' from deleted as d join inserted as i on d.codigo=i.codigo end else begin raiserror('El precio y stock no pueden modificarse. La actualización no se realizó.', 10, 1) rollback transaction end;
Empleamos "if update" para que el trigger controle si la actualización se realiza en ciertos campos permitidos (titulo, autor y editorial) y no en los campos prohibidos (precio y stock)); si se modifican los campos permitidos y ninguno de los no permitidos, mostrará los antiguos y nuevos valores consultando las tablas "deleted" e "inserted", en caso que se actualice un campo no permitido, el disparador muestra un mensaje y deshace la transacción.
Note que el disparador no controla los intentos de actualización sobre el campo "codigo", esto es porque tal campo, no puede modificarse porque está definido "identity", si intentamos modificarlo, SQL Server muestra un mensaje de error y el trigger no llega a dispararse.