Está en la página 1de 11

UTEC C01/2019 BAS2

Triggers (Disparador o Desencadenador)


Definición de Trigger
Un disparador es una clase especial de procedimiento almacenado que se ejecuta automáticamente cuando
se produce un evento en el servidor de bases de datos. Los disparadores DML se ejecutan cuando un usuario
intenta modificar datos mediante un evento de lenguaje de manipulación de datos (DML). Los eventos DML
son instrucciones INSERT, UPDATE o DELETE de una tabla o vista. Estos desencadenadores se activan cuando
se desencadena cualquier evento válido, con independencia de que las filas de la tabla se vean o no
afectadasi.
Sintaxis:
CREATE TRIGGER [ schema_name . ]trigger_name
ON { table | view }
[ WITH <dml_trigger_option> [ ,...n ] ]
{ FOR | AFTER | INSTEAD OF }
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > }

<dml_trigger_option> ::=
[ ENCRYPTION ]
[ EXECUTE AS Clause ]

<method_specifier> ::=
assembly_name.class_name.method_name

Ejemplo de implementación de Trigger’s


Para el desarrollo de estos ejemplos estableceremos un escenario, el cual esta relacionado a una parte del
modelo de inventarios y compras, donde las tablas serian de productos, exitencias, categorías y compras, dicho
lo anterior comenzamos a desarrollar nuestra ambiente de pruebas siguiendo los siguientes pasos.

Primeramente definiremos las tablas a utilizar en este ejemplo ver diagrama ER.

Figura 0: Diagrama E-R


NERM Pagina 1 de 11
UTEC C01/2019 BAS2
Definimos una base de datos de nombre modeltriggers y la ponemos en uso.
create database modeltiggers;
use modeltiggers;

Definimos las tablas que utilizaremos.


create table Categorias
(
codi_cate int not null identity(1,1),
nomb_cate varchar(75) not null
);
create table Productos
(
codi_prod int not null identity(1,1),
codi_cate int not null,
nomb_prod varchar(125) not null
);
create table Existencias
(
id_exit int not null identity(1,1),
codi_prod int not null,
unid_prod numeric(38,10) not null
);
create table [Encabezado Compra]
(
nume_fact int identity(1,1) not null,
fech_fact date not null,
tota_comp money not null
);
create table [Detalle Compra]
(
Id_deta int identity(1,1) not null,
codi_prod int not null,
nume_fact int not null,
nume_unid numeric(38,10),
prec_unit money
);

Definimos las llaves primarias y después la foraneas.


alter table
Categorias add constraint pk_codi_cate primary key (codi_cate);
alter table
Productos add constraint pk_codi_prod primary key (codi_prod);
alter table
Existencias add constraint pk_id_exit primary key (id_exit);
alter table
[Encabezado Compra] add constraint pk_nume_fact primary key (nume_fact);
alter table
[Detalle Compra] add constraint pk_Id_deta primary key (Id_deta);
alter table
Productos add constraint fk_codi_cate foreign key (codi_cate)
references Categorias (codi_cate);
alter table Existencias add constraint fk_codi_prod foreign key (codi_prod)
references Productos (codi_prod);
alter table [Detalle Compra] add constraint fk_codi_prod1 foreign key (codi_prod)
references Productos (codi_prod);
alter table [Detalle Compra] add constraint fk_nume_fact foreign key (nume_fact)
references [Encabezado Compra] (nume_fact);

Definiremos unos datos de categorias en la tabla Categorias.


Insert Categorias (nomb_cate) values ('Llaves'), ('Tornillos'), ('Focos'), ('Plantas');

Definiremos un trigger de inserción, en la tabla productos, porque, debido a que siempre que se crea un
producto es necesario crear el código en la tabla de Existencias.
create trigger ins_productos on Productos
for insert
as
NERM Pagina 2 de 11
UTEC C01/2019 BAS2
begin
declare @vcodi_prod int
select @vcodi_prod=codi_prod from inserted
insert Existencias (codi_prod, unid_prod) values (@vcodi_prod, 0.0)
end

Ahora probaremos el trigger, ello se lograra, insertando un producto, por ello insertamos los datos de un
tornillo de 1 pulgada para madera, esto estaría en la categoría 2, esto lo conocemos ejecutando:
select * from Categorias

Figura 1: listado de tabla Categorias.

Ahora insertamos el datos:


insert Productos (codi_cate, nomb_prod) values (2,'Tornillo de 1 Pulgada para Madera');

Figura 2: Insertamos un producto y se observa que el resultado es de 2 filas afectadas.

Para verificar que se ha realizado la inserción del producto y el funcionamiento del trigger, ejecutamos lo
siguiente:
select * from Productos;
select * from Existencias;

El resultado lo podemos apreciar en la imagen (Fig. 1)

NERM Pagina 3 de 11
UTEC C01/2019 BAS2

Figura 3: Listado los datos de las tablas Productos y Existencias.

Insertamos una serie de productos para realizar posteriormente otras pruebas.


insert Productos (codi_cate, nomb_prod) values (2,'Tornillos 1/4 para Metal');
insert Productos (codi_cate, nomb_prod) values (2,'Tornillos1/2 para Concreto');
insert Productos (codi_cate, nomb_prod) values (1,'Llave 1/4 plg.');
insert Productos (codi_cate, nomb_prod) values (1,'Lllave 1/2 plg.');
insert Productos (codi_cate, nomb_prod) values (1,'Llave # 11');
insert Productos (codi_cate, nomb_prod) values (1,'Llave #7');
insert Productos (codi_cate, nomb_prod) values (3,'Foco 20 Watt Luz Blanca');
insert Productos (codi_cate, nomb_prod) values (3,'Foco 40 Watt Luz Blanca');
insert Productos (codi_cate, nomb_prod) values (3,'Foco 60 Watt Luz Blanca');
insert Productos (codi_cate, nomb_prod) values (3,'Foco 15 Watt Luz Blanca LED');
insert Productos (codi_cate, nomb_prod) values (3,'Foco 30 Watt Luz Blanca LED');
insert Productos (codi_cate, nomb_prod) values (3,'Foco 40 Watt Luz Blanca LED');
insert Productos (codi_cate, nomb_prod) values (4,'Natural de Sombra K');
insert Productos (codi_cate, nomb_prod) values (4,'Palmare Ornamental');
insert Productos (codi_cate, nomb_prod) values (4,'Artificial laurel');
insert Productos (codi_cate, nomb_prod) values (4,'Aritificial Pino');

Definir trigger de tipo insercion (insert), en la tabla Detalle Compra que permitirá actualizar, la existencia del
artículo, incrementando el número de unidades en la medida que agreguemos una compra de dicho Producto
y a la vez que actualice el total en valor de la compra en la tabla Encabezado Compra.
create trigger ins_DetallaCompra on [Detalle Compra]
for insert
as
begin
declare @vcodi_prod int,
@vnume_fact int,
@vnume_unid numeric(38,10),
@vprec_unit money,
@vprec_tota money
--Obtenemos los datos del nuevo registro y lo asignamos a variables
select @vcodi_prod=codi_prod,@vnume_unid=nume_unid,@vprec_unit=prec_unit
from inserted
--Establecemos el total precio del producto al realizar una multiplicacion
--del numero de articulos por precio unitario.
select @vprec_tota=@vprec_unit * @vnume_unid
--Actualizamos la existencia, al incrementarla.
update Existencias
set unid_prod=unid_prod + @vnume_unid
where codi_prod=@vcodi_prod
--Actualizamos el total de la compra en encabezado de la compra.
NERM Pagina 4 de 11
UTEC C01/2019 BAS2
update [Encabezado Compra]
set tota_comp=tota_comp + @vprec_tota
end

Creamos el encabezado de compras con la siguiente instrucción.


insert [Encabezado Compra] (fech_fact, tota_comp) values (cast(getdate() as date),0.00);

Recuperamos el dato de Encabezado Compra para tener el número de factura (nume_fact)

Figura 4: Obteniendo el número del encabezado de compra.

Ahora insertamos un nuevo registro en el detalle de la compra, para nuestro caso el producto con Id = 4 que
es Llave 1/4 plg., y un precio unitario 7.5 para 5 unidades, que representaría un total de 37.50, este total seria
el valor del encabezado de compra.
insert [Detalle Compra] (codi_prod,nume_fact,nume_unid,prec_unit) values (4,1,5,7.5);

Ahora revisamos, que nuestro trigger haya realizado la actualización en la tablas Encabezado Compra y
Existencias.

Figura 5: Listado de datos en las tablas donde registramos el dato.


Ahora agregamos otro producto a la factura para esta caso con código producto 3.
insert [Detalle Compra] (codi_prod,nume_fact,nume_unid,prec_unit) values (3,1,4,2.75);

Realizamos una revisión de nuestras tablas con consultas.

NERM Pagina 5 de 11
UTEC C01/2019 BAS2

Figura 6: Consulta del registro insertado y que afecto las tablas relacionadas con el triggers.

Muy importante observar entre la figura 5 y 6 la columna de nombre tota_comp, que el valor se incrementó
con el nuevo registro agregado en el detalle de compra.

Ahora creamos un trigger para actualizar los datos (update), consideremos el hecho que se modificó el número
de unidades para el registro con Id_deta = 1, ya no son 5 sino que 8, esto siginifica que debemos incrementar
el número de unidades de existencia en tres y el precio total de la compra (tota_comp) por los tres productos
adicionales, un hecho importante a tener en cuenta que la modificación de un registro en la tabla Detalle
Compra, ocurrirá siempre porque actualizamos el registro, por ello debemos validar y enfocar que se modifica
o actualiza para que el trigger funcione adecuadamente, a continuación detallamos la estructura del trigger:
create trigger upd_DetalleCompra on [Detalle Compra]
for update
as
begin
declare @vcodi_prod int,
@vnume_fact int,
@vnume_unid_new numeric(38,10),
@vprec_unit_new money,
@vnume_unid_old numeric(38,10),
@vprec_unit_old money,
@vprec_tota money,
@vnume_unid numeric(38,10)
--Para este caso considerando que la actualizacion la realizamos por
--cantidad de producto significa que el codigo de producto y numero de factura
--es la misma por ello este dato no cambia
select @vcodi_prod=codi_prod, @vnume_fact=nume_fact from inserted
--Obtenemos los datos nuevos que ingresamos
select @vnume_unid_new=nume_unid, @vprec_unit_new=prec_unit from inserted
--Obtenemos los datos anteriores que se reemplazan
select @vnume_unid_old=nume_unid, @vprec_unit_old=prec_unit from deleted
--Obtenemos el valor total de factura
select @vprec_tota=tota_comp from [Encabezado Compra] where nume_fact=@vnume_fact
if update(nume_unid)
begin
--Calculando el valor total de factura y actualizando
set @vnume_unid=@vnume_unid_new - @vnume_unid_old
set @vprec_tota=@vprec_tota + (@vnume_unid * @vprec_unit_old)
update [Encabezado Compra] set tota_comp=@vprec_tota where nume_fact=@vnume_fact
--Actualizamos el numero de unidades de existencia
update [Existencias] set unid_prod=unid_prod + @vnume_unid where codi_prod=@vcodi_prod
NERM Pagina 6 de 11
UTEC C01/2019 BAS2
end
end

Realizamos la actualización, debido a que previamente hemos compilado el trigger.


update [Detalle Compra] set nume_unid=8 where Id_deta=1;

Consultamos los datos y revisamos.

Figura 7: Lista de datos de tablas afectadas, después de actualizar.

Observe que se incrementó el precio y número de unidades en tres porque anteriormente (ver Fig. 6) teníamos
5 unidades y en valor de la factura 48.50, el trigger funciona pero que sucede si cambian el precio unitario ya
no es 7.50 sino que 6.75, por ello modificaremos el trigger y ahora validamos cuando cambie el valor la columna
prec_unit, antes de realizar este cambio, modificar y actualizar el trigger.
alter trigger upd_DetalleCompra on [Detalle Compra]
for update
as
begin
declare @vcodi_prod int,
@vnume_fact int,
@vnume_unid_new numeric(38,10),
@vprec_unit_new money,
@vnume_unid_old numeric(38,10),
@vprec_unit_old money,
@vprec_tota money,
@vprec_tota_ori money,
@vnume_unid numeric(38,10)
--Para este caso considerando que la actualizacion la realizamos por cantidad de producto
--significa que el codigo de producto y numero de factura es la misma por ello este dato no
--cambia
select @vcodi_prod=codi_prod, @vnume_fact=nume_fact from inserted
--Obtenemos los datos nuevos que ingresamos
select @vnume_unid_new=nume_unid, @vprec_unit_new=prec_unit from inserted
--Obtenemos los datos anteriores que se reemplazan
select @vnume_unid_old=nume_unid, @vprec_unit_old=prec_unit from deleted
--Obtenemos el valor total de factura
select @vprec_tota_ori=tota_comp from [Encabezado Compra] where nume_fact=@vnume_fact
if update(nume_unid)
begin
set @vprec_tota=@vprec_tota_ori
--Calculando el valor total de factura y actualizando
NERM Pagina 7 de 11
UTEC C01/2019 BAS2
set @vnume_unid=@vnume_unid_new - @vnume_unid_old
set @vprec_tota=@vprec_tota + (@vnume_unid * @vprec_unit_old)
update [Encabezado Compra] set tota_comp=@vprec_tota where nume_fact=@vnume_fact
--Actualizamos el numero de unidades de existencia
update [Existencias] set unid_prod=unid_prod + @vnume_unid where codi_prod=@vcodi_prod
end
if update(prec_unit)
begin
set @vprec_tota=@vprec_tota_ori
--Calculamos el precio total con nuevo precio
set @vprec_tota=@vprec_tota - (@vnume_unid_old * @vprec_unit_old)
set @vprec_tota=@vprec_tota + (@vnume_unid_new * @vprec_unit_new)
--Actualizamos el monto total de la factura
update [Encabezado Compra] set tota_comp=@vprec_tota where nume_fact=@vnume_fact
end
end

Realizado la actualizacion de trigger ejecutar la actualizacion y revisar cambios


update [Detalle Compra] set prec_unit=6.75 where Id_deta=1;

Figura 8: Se observa que el cambio se ha realizado sin inconveniente.


Ahora bien realizaremos una modificación de unidade y precio en un mismo momento y validaremos con
esto si el trigger procede con actualizacion del dato para ambos cambios.
update [Detalle Compra] set prec_unit=3.25, nume_unid=6 where Id_deta=2;

NERM Pagina 8 de 11
UTEC C01/2019 BAS2

Figura 9: Cambio realizado y el total sin error.

Registraremos una nueva compra los datos son los siguientes:


insert [Encabezado Compra] (fech_fact, tota_comp) values (cast(getdate() as date),0.00);
insert [Detalle Compra] (codi_prod,nume_fact,nume_unid,prec_unit) values (15,2,25,12.5);
insert [Detalle Compra] (codi_prod,nume_fact,nume_unid,prec_unit) values (17,2,75,15.25);

Figura 10: Lista de datos de la segunda compra registrada.

Ya tenemos el trigger de inserción para cuando registramos un ítem en el Detalla Compra asi como
controlado la actualizacion de uno existente, pero que sucede si borramos un ítem, este debe actualizar tanto
la existencia como el total del Encabezado Compra, para la compra numero 2 agregaremos un nuevo ítem
para el producto con código 7 y después lo eliminaremos.
insert [Detalle Compra] (codi_prod,nume_fact,nume_unid,prec_unit) values (7,2,25,22.73);

NERM Pagina 9 de 11
UTEC C01/2019 BAS2

Figura 11: Confirmando que la compra 2 tiene tres productos, registrados.

Definición de trigger para cuando se borra un ítem en Detalle Compra.


create trigger del_DetalleCompra on [Detalle Compra]
for delete
as
begin
declare @vcodi_prod int,
@vnume_fact int,
@vnume_unid numeric(38,10),
@vprec_unit money,
@vprec_tota money
--Para el caso del borrado recuperamos los datos del registro a borrar
--despues aplicaremos la disminucion tanto en numero de unidades como
--de valor del encabezado
--Obtenemos los datos que se borraran
select @vcodi_prod=codi_prod,@vnume_fact=nume_fact,
@vnume_unid=nume_unid,@vprec_unit=prec_unit
from deleted
--Obtenemos el valor total de factura
set @vprec_tota=@vprec_unit * @vnume_unid
--Actualizamos la existencia, en disminuir lo eliminado.
update Existencias
set unid_prod=unid_prod - @vnume_unid
where codi_prod=@vcodi_prod
--Actualizamos el total de la compra en encabezado de la compra.
update [Encabezado Compra]
set tota_comp=tota_comp - @vprec_tota
end
Borramos el ítem numero 5 de Detalle Compra.
delete [Detalle Compra] where Id_deta=5

NERM Pagina 10 de 11
UTEC C01/2019 BAS2

Figura 12: Efectivamente registro borrado y actualizado tanto existencia y valor de Encabezado.

Bibliografia
https://msdn.microsoft.com/en-us/library/ms189799(v=sql.110).aspx
https://msdn.microsoft.com/es-es/library/ms178110.aspx
https://msdn.microsoft.com/es-es/library/ms189799.aspx

i
Definicion tomada de https://msdn.microsoft.com/es-es/library/ms189799.aspx

NERM Pagina 11 de 11

También podría gustarte