0% encontró este documento útil (0 votos)
243 vistas43 páginas

Trigger (Disparadores) Exposiciòn Final Lunes Taller de Base

Descargar como pptx, pdf o txt
Descargar como pptx, pdf o txt
Descargar como pptx, pdf o txt
Está en la página 1/ 43

Trigger

Ayala Viera Piero


Bautista Castañeda Aaron
Montalvo Amaya Jhen
Moran Diaz Juan Maximo
Vilchez Masquez José Roger
CONCEPTO
Los disparadores (o triggers) son bloques de código PL/SQL asociados a una tabla y que se ejecutan
automáticamente como reacción a una operación DML específica (INSERT, UPDATE o DELETE) sobre dicha
tabla.

TIPOS DE TRIGGER

CATEGORIA VALORES COMENTARIOS


INSERT, DELETE, Define el tipo de operación DML provoca la activación del
ORDEN
UPDATE trigger.
TEMPORIZACI Define si el disparador se activa antes o después de que se
BEFORE o AFTER
ÓN ejecute la operación DML
Los disparadores con nivel de fila se activan una vez por cada
fila afectada por la orden que provocó el disparo. Los Triggers
NIVEL FILA u ORDEN con nivel de orden se activan sólo una vez, antes o después de la
orden. Los disparadores con nivel de fila se identifican por la
cláusula FOR EACH ROW en la definición del disparador.
Orden de ejecución
Una misma tabla puede tener varios triggers asociados. En tal caso es necesario conocer el orden en el
que se van a ejecutar.
Los disparadores se activan al ejecutarse la sentencia SQL.

 Si existe, se ejecuta el disparador de tipo BEFORE (disparador previo) con nivel de orden.
 Para cada fila a la que afecte la orden:
 Se ejecuta si existe, el disparador de tipo BEFORE con nivel de fila.
 Se ejecuta la propia orden.
 Se ejecuta si existe, el disparador de tipo AFTER (disparador posterior) con nivel de fila.
 Se ejecuta, si existe, el disparador de tipo AFTER con nivel de orden.
RESTRICCIONES

El cuerpo de un disparador es un bloque PL/SQL. Cualquier orden que sea legal en un bloque
PL/SQL , es legal en el cuerpo de un disparador, con las siguientes restricciones:

 Un disparador no puede emitir ninguna orden de control de transacciones ( COMMIT,


ROLLBACK o SAVEPOINT). El disparador se activa como parte de la ejecución de la orden
que provocó el disparo, y forma parte de la misma transacción qu dicha orden. Cuando la
orden que provoca la orden es confirmada o cancelada, se confirma o se cancela también el
trabajo realizado por el disparador.

 Por las mismas razones, ningún procedure o función llamado por el disparador puede emitir
órdenes de control de transacciones.

 El disparador no puede declarar variables de tipo LONG.


Utilización de :old y :new en los disparadores con nivel
de fila.
Un disparador con nivel de fila se ejecuta una vez por cada fila procesada por la orden que provoca el disparo.
Dentro del disparador, puede accederse a la fila que está siendo actualmente procesada utilizando, para ello, dos
pseudo-registros, :old y :new.
En principio tanto :old como :new son del tipo tabla_disparo%ROWTYPE;

ORDEN DE :old :new


DISPARO
No definido; todos los campos toman Valores que serán insertados cuando se complete
INSERT
el valor NULL. la orden
Valores originales de la fila, antes Nuevos valores que serán escritos cuando se
UPDATE
dela actualización. complete la orden.
Valores originales, antes del borrado No definido; todos los campos toman el valor
DELETE
de la fila. NULL.
EJEMPLOS:
 EJEMPLO 01:
DELIMITER $$
CREATE TRIGGER trigger_cliente_historico 
AFTER INSERT ON cliente
FOR EACH ROW
BEGIN 
   INSERT INTO cliente_historico(nombre, dni, direccion)
   VALUES (NEW.nombre, NEW.dni, NEW.direccion, CURDATE());
END; $$
 EJEMPLO 02:
CREATE OR REPLACE TRIGGER Fila_Cuenta_Empleados
AFTER DELETE OR INSERT OR UPDATE OF Dpto ON Empleados FOR EACH ROW
DECLARE Indice BINARY_INTEGER;
BEGIN
Indice := Empleados_Dpto.Tabla_Dptos.COUNT + 1;
IF INSERTING THEN
Empleados_Dpto.Tabla_Dptos(Indice) := :new.Dpto;
ELSIF UPDATING THEN
Empleados_Dpto.Tabla_Dptos(Indice) := :new.Dpto;
Empleados_Dpto.Tabla_Dptos(Indice+1):= :old.Dpto;
ELSE Empleados_Dpto.Tabla_Dptos(Indice) := :old.Dpto;
END IF;
END Fila_Cuenta_Empleados;
Disparadores (Triggers)
 Los triggers son bloques PL/SQL que se ejecutan
de manera implícita cuando se ejecutan
operaciones (eventos DML) INSERT, DELETE,
UPDATE a una tabla*.
 Se usan principalmente para establecer reglas
complejas de integridad y labores de auditoría.
¿Por ejemplo?

* También existen triggers que se disparan ante eventos de DDL (ej.


BEFORE DDL) y eventos de database (ej. LOGON y LOGOFF) y sobre otros
objetos de la BD (vistas, DATABASE, entre otros).
 Un trigger tiene asociado:

 Un evento
 Un momento
 Un tipo

 El evento se refiere a la operación que se efectúa sobre la tabla (INSERT, DELETE o UPDATE).

• El momento, se refiere a cuándo se dispara el trigger en relación con el evento.


Sus posibles valores son BEFORE y AFTER*.
• El tipo indica el número de veces que el cuerpo del trigger se ejecuta: por la
operación en conjunto (trigger de operación) o por cada fila procesada (trigger
de fila). En este último caso se debe adicionar la cláusula FOR EACH ROW
Sintaxis esencial de un trigger:

CREATE [OR REPLACE] TRIGGER nombre_trigger


momento evento ON tabla
[FOR EACH ROW Para especificar
triggers de fila
[WHEN condición]]
bloque de PL/SQL

Si el evento es UPDATE, se puede(n) especificar


la(s) columna(s) que dispararán el trigger con la palabra
OF (si no se especifican, el trigger se dispara con cualquier
columna de la tabla que sea actualizada)

El bloque comienza con la palabra DECLARE o BEGIN


Ejemplo: Trigger de operación

CREATE TABLE PRODUCTO(codigo NUMBER(6) PRIMARY KEY,


precio NUMBER(6));

CREATE OR REPLACE TRIGGER control_insercion_productos


Domingo (puede ser 1 o 7
BEFORE INSERT ON producto según la config. del NLS)
BEGIN
IF TO_CHAR(SYSDATE,'D') = '7'THEN
RAISE_APPLICATION_ERROR(-20506,'¡No los domingos!');
END IF;
SQLCODE y SQLERRM asignados por el usuario
END;
/

La instrucción RAISE_APPLICATION_ERROR abortará la operación de inserción si


esta se intenta hacer un domingo.
BEGIN
INSERT INTO producto VALUES(1,10);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE || SQLERRM);
END;
/
Ejemplo: Trigger de Fila

Sean las tablas:

CREATE TABLE cuenta(


nro_cta NUMBER(10) PRIMARY KEY,
saldo NUMBER(8) NOT NULL CHECK (saldo >= 0)
);

INSERT INTO cuenta VALUES(1, 100);


INSERT INTO cuenta VALUES(2, 200);

CREATE TABLE retiro(


nro_retiro NUMBER(10) PRIMARY KEY,
cta NUMBER(10) REFERENCES cuenta NOT NULL,
valor NUMBER(8) NOT NULL CHECK (valor > 0)
);
CREATE OR REPLACE TRIGGER control_retiro
BEFORE INSERT ON retiro
FOR EACH ROW
DECLARE
saldo_cta cuenta.saldo%TYPE;
BEGIN
SELECT saldo INTO saldo_cta
FROM cuenta WHERE nro_cta = :NEW.cta;
IF saldo_cta < :NEW.valor THEN
RAISE_APPLICATION_ERROR(-20505,'¡Fondos insuficientes!');
ELSE
UPDATE cuenta SET saldo = saldo - :NEW.valor
WHERE nro_cta = :NEW.cta;
END IF;
END;
¿Qué pasa si el valor del
/ retiro fuese negativo?
La cláusula WHEN

 Sirve para agregar una condición adicional para activar el trigger


 Dentro de la condición WHEN para referirse a NEW y a OLD no se usan
los dos puntos (:)

Ejemplo. Sea:

CREATE TABLE auditoria


(usuario VARCHAR2(20),cuando DATE, cta NUMBER(6), aumento
NUMBER(10));
Usando WHEN: Sin usar WHEN:
CREATE or REPLACE TRIGGER CREATE or REPLACE TRIGGER
quien_sube_retiro quien_sube_retiro
BEFORE UPDATE OF valor ON retiro BEFORE UPDATE OF valor ON retiro
FOR EACH ROW FOR EACH ROW
WHEN (NEW.valor > OLD.valor) BEGIN
BEGIN IF :NEW.valor > :OLD.valor
INSERT INTO auditoria THEN
VALUES(USER, SYSDATE, :old.cta, INSERT INTO auditoria
:NEW.valor - :OLD.valor );
VALUES(USER, SYSDATE, :old.cta,
END; :NEW.valor - :OLD.valor );
/ END IF;
END;
/

Conclusión: WHEN evita el uso de un IF explícito dentro


de la sección ejecutable del trigger
Ejemplo

 Para graficar con un ejemplo la idea de un Desencadenador


implementaremos uno, piense en la siguiente situación:

 Al agregar un nuevo pedido a la tabla de PEDIDOS se debe


incrementar las ventas del representante que concreto el pedido, así
como también debe reducirse el número de existencias.
Ejemplo
 Para ello debe crear el siguiente Desencadenador:

Use Ejemplo
GO
CREATE TRIGGER NuevoPedido
ON Pedidos
FOR INSERT
AS
UPDATE RepVentas
SET VENTAS =VENTAS + INSERTED.IMPORTE
FROM REPVENTAS INNER JOIN INSERTED
ON REPVENTAS.NUM_EMPL = INSERTED.REP
UPDATE PRODUCTOS
SET EXISTENCIAS = EXISTENCIAS - INSERTED.CANT
FROM PRODUCTOS INNER JOIN INSERTED
ON PRODUCTOS.ID_FAB = INSERTED.FAB
AND PRODUCTOS.ID_PRODUCTO = INSERTED.PRODUCTO
GO
Ejemplo
 Para comprobar la ejecución de este Desencadenador ejecute las siguientes
sentencias:
 Antes de ejecutar un INSERT de prueba, mostraremos la información con respecto
a un producto
Select * From Productos Where Id_Fab= 'ACI' AND Id_Producto='41001'
GO
Ejemplo

 Ahora la de un representante de ventas


Select nombre, cuota, ventas From RepVentas Where num_empl = 104
GO
Ejemplo
 Ahora agregaremos un pedido
Insert Pedidos Values (111000, '5/15/1996', 2101, 104, 'ACI', '41001', 5, 275)
GO
 Verifique los resultados anteriores
Select * From Productos Where Id_Fab= 'ACI' AND Id_Producto='41001'
GO
Ejemplo
Select nombre, cuota, ventas From RepVentas Where num_empl = 104
GO

Como se comprobó al agregar un nuevo pedido


automáticamente el Desencadenador funciona y actualiza
las ventas para el representantes de ventas y reduce el
número de existencias en stock.
MODIFICACION DE TRIGGERS

 Los triggers se crean con la instrucción "create trigger" seguido del nombre del disparador. Si se agrega
"or replace" al momento de crearlo y ya existe un trigger con el mismo nombre, tal disparador será
borrado y vuelto a crear, de esta manera se puede modificar.

create or replace trigger NOMBREDISPARADOR


MOMENTO-- before, after o instead of
EVENTO-- insert, update o delete
of CAMPOS-- solo para update
on NOMBRETABLA
NIVEL--puede ser a nivel de sentencia (statement) o de fila (for each row)
when CONDICION--opcional
begin
CUERPO DEL DISPARADOR--sentencias
end NOMBREDISPARADOR;
CUANTAS VECES SE DESENCADENARA, FILAS O
SENTENCIAS
 Disparador de actualización a nivel de fila

En caso que una sola sentencia "update" modifique varios registros en la tabla asociada, el trigger se disparará
una sola vez; si queremos que se active una vez por cada registro afectado, debemos indicarlo con "for each
row".

La siguiente es la sintaxis para crear un trigger de actualización a nivel de fila, se dispare una vez por cada fila
modificada sobre la tabla especificada:

create or replace trigger NOMBREDISPARADOR


MOMENTO update
on NOMBRETABLA
for each row
begin
CUERPO DEL TRIGGER;
end NOMBREDISPARADOR;
 Creamos un desencadenador a nivel de fila, que se dispara una vez por cada fila afectada por
un "update" sobre la tabla "libros". Se ingresa en la tabla "control" el nombre del usuario
que altera la tabla "libros" (obtenida mediante la función "user") y la fecha en que lo hizo
(mediante la función "sysdate"):

create or replace trigger tr_actualizar_libros


before update
on libros
for each row
begin
insert into control values(user,sysdate);
end tr_actualizar_libros;

 Si al ejecutar un "update" sobre "libros" se actualizan 5 registros, en la tabla "control" se


ingresarán 5 registros, uno por cada modificación. Si el trigger hubiese sido definido a nivel
de sentencia (statement), se agregaría una sola fila en "control".
 Disparador de inserción a nivel de sentencia
 Un disparador está asociado a una tabla y a una operación específica (inserción,
actualización o borrado). A continuación veremos la creación de un disparador para el
evento de inserción: "insert triger“.

 La siguiente es la sintaxis para crear un trigger de inserción que se dispare cada vez que
se ejecute una sentencia "insert" sobre la tabla especificada, es decir, cada vez que se
intenten ingresar datos en la tabla:

create or replace trigger NOMBREDISPARADOR


MOMENTO insert
on NOMBRETABLA
begin
CUERPO DEL TRIGGER;
end NOMBREDISPARADOR;

 Analizamos la sintaxis:
Luego de la instrucción "create trigger" se coloca el nombre del disparador. Si se agrega "or
replace" al momento de crearlo y ya existe un trigger con el mismo nombre, tal disparador será
borrado y vuelto a crear.
- "MOMENTO" indica cuando se disparará el trigger en relación al evento, puede se BEFORE
(antes) o AFTER (después). Se especifica el evento que causa que el trigger se dispare, en este caso
"insert", ya que el trigger se activará cada vez que se ejecute la sentencia "insert" sobre la tabla
especificada luego de "on".

- Es un trigger a nivel de sentencia, es decir, se dispara una sola vez por cada sentencia "insert",
aunque la sentencia ingrese varios registros. Es el valor por defecto si no se especifica.

- Finalmente se coloca el cuerpo del trigger dentro del bloque "begin.. end".

Ejemplo:
Creamos un desencadenador que se dispara cada vez que se ejecuta un "insert" sobre la tabla
"libros":

create or replace trigger tr_ingresar_libros


before insert
on libros
begin
insert into Control values(user, sysdate);
end tr_ingresar_libros;
TRIGGERS DE ELIMINACIÓN
Podemos crear un disparador para que se ejecute siempre que una instrucción "delete" elimine datos en
una tabla.

Sintaxis básica:

create trigger NOMBREDISPARADOR


on NOMBRETABLA
for delete
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 "delete"), lo que indica que las eliminaciones sobre la
tabla activarán el trigger.
• Luego de "as" se especifican las condiciones que determinan cuando un intento de eliminación causa las
acciones que el trigger realizará.
 El disparador del siguiente ejemplo se crea para la tabla "ventas", para que cada vez que se elimine un
registro de "ventas", se actualice el campo "stock" de la tabla "libros" (por ejemplo, si el comprador
devuelve los libros comprados):

create trigger DIS_ventas_borrar


on ventas
for delete
as
update libros set stock= libros.stock+deleted.cantidad
from libros
join deleted
on deleted.codigolibro=libros.codigo;

 Cuando se activa un disparador "delete", los registros eliminados en la tabla del disparador se agregan
a una tabla llamada "deleted". La tabla "deleted" es una tabla virtual que conserva una copia de los
registros eliminados; tiene una estructura similar a la tabla en que se define el disparador, es decir, la
tabla en que se intenta la acción.

 Dentro del trigger se puede acceder a esta tabla virtual "deleted".


 El siguiente disparador se crea para controlar que no se elimine más de un registro de la tabla "libros".
El disparador se activa cada vez que se elimina un registro o varios, controlando la cantidad de registros
que se están eliminando; si se está eliminando más de un registro, el disparador retorna un mensaje de
error y deshace la transacción:

create trigger DIS_libros_borrar


on libros
for delete
as
if (select count(*) from deleted) > 1
begin
raiserror('No puede borrar más de un libro',16,1)
rollback transaction
end;

 Si se ejecuta un "delete" sobre "libros" que afecte a varios registros, se activa el disparador y evita la
transacción.
 Si se ejecuta el siguiente "delete", que afecta a un solo registro, se activa el disparador y permite la
transacción:
delete from libros where codigo=5;

 La sentencia "truncate table" no puede incluirse en un disparador de borrado (delete trigger).


CASO:
Usando la base de datos Northwind

 Para utilizar un Trigger de tipo instead of crearemos una vista llamada SociosEstrategicos con los Clientes
(Customers) y los Proveedores (Suppliers)
Creamos la vista
Create view VistaSociosEstrategicos
As
select C.CustomerID ‘CodigoSocio’, C.CompanyName As ‘Socio’,
C.Country As ‘País’, ‘Cliente’ As Tipo
from Customers As C
union all
select S.SupplierID , S.CompanyName ,
S.Country , ‘Proveedor’ As Tipo
from Suppliers As S
go
El Trigger se creará para la vista, será de tipo Instead Of

create trigger trVistaSocioEstrategicoInsertar


on VistaSociosEstrategicos
instead of insert
as
insert into Customers (CustomerID, CompanyName,
Country)
select CodidoSocio,Socio,País
from inserted where Tipo=’Cliente’

insert into Suppliers (CompanyName, Country)


select Socio,País
from inserted where Tipo=’Proveedor’
go
Insertar un Cliente
insert into VistaSociosEstrategicos
values (‘YT348′,’Sociedad SQL’,’France’,’Cliente’)
go

Insertar un Proveedor
insert into VistaSociosEstrategicos
values (‘BT599′,’Limbo Almacenes’,’Spain’,’Proveedor’)
go
Más ejemplos de desencadenadores

 Para crear un Desencadenador puede utilizar el siguiente formato:


CREATE TRIGGER<Nombre del Desencadenador>
ON <Nombre de la Tabla>
FOR <INSERT l UPDATE l DELETE>
AS
Sentencias….
GO
Ejemplo 1

 Para graficar con un ejemplo la idea de un Desencadenador implementaremos uno,


piense en la siguiente situación:

 Al agregar un nuevo pedido a la tabla de PEDIDOS se debe incrementar las ventas


del representante que concreto el pedido, así como también debe reducirse el número
de existencias.
Ejemplo 1
 Para ello debe crear el siguiente Desencadenador:

Use Ejemplo
GO
CREATE TRIGGER NuevoPedido
ON Pedidos
FOR INSERT
AS
UPDATE RepVentas
SET VENTAS =VENTAS + INSERTED.IMPORTE
FROM REPVENTAS INNER JOIN INSERTED
ON REPVENTAS.NUM_EMPL = INSERTED.REP
UPDATE PRODUCTOS
SET EXISTENCIAS = EXISTENCIAS - INSERTED.CANT
FROM PRODUCTOS INNER JOIN INSERTED
ON PRODUCTOS.ID_FAB = INSERTED.FAB
AND PRODUCTOS.ID_PRODUCTO = INSERTED.PRODUCTO
GO
Ejemplo: Desencadenadores DDL

CREATE TRIGGER safety ON DATABASE


FOR DROP_TABLE, ALTER_TABLE AS
PRINT ‘debe desactivar el trigger de seguridad para eliminar o modificar las tablas’
ROLLBACK ;
Desencadenadores LOGON

 Todos los mensajes que se originan dentro del desencadenador que alcanzaría
normalmente el usuario, como los mensajes de error y los mensajes de la instrucción
PRINT, se desvían al registro de errores de SQL Server.

 Los desencadenadores logon no se activan si se produce un error en la autenticación.


Ejemplo: Desencadenadores LOGON

USE master;
GO CREATE LOGIN login_test
WITH PASSWORD = '3KHJ6dhx(0xVYsdf' MUST_CHANGE, CHECK_EXPIRATION = ON;
GO GRANT VIEW SERVER STATE TO login_test;
GO CREATE TRIGGER connection_limit_trigger ON ALL SERVER WITH EXECUTE AS
'login_test' FOR LOGON AS
BEGIN
IF ORIGINAL_LOGIN()= 'login_test' AND (SELECT COUNT(*) FROM
sys.dm_exec_sessions WHERE is_user_process = 1 AND original_login_name = 'login_test') > 3
ROLLBACK;
END;
Diferencias entre desencadenadores DML y
DDL
 Los desencadenadores DDL y DML se utilizan con finalidades distintas.

 Los desencadenadores DML funcionan con las instrucciones INSERT,


UPDATE y DELETE, y permiten exigir las reglas de negocios y extender la
integridad de los datos cuando se modifican datos en tablas o vistas.
Diferencias entre desencadenadores DML y
DDL
 Los desencadenadores DDL funcionan en instrucciones DDL CREATE, ALTER,
DROP entre otras, y en procedimientos almacenados que realizan operaciones
similares a DDL. Se utilizan para realizar tareas administrativas y exigir las reglas de
negocios que afectan a las bases de datos.

 Se aplican a todos los comandos de un solo tipo en toda una base de datos o todo un
servidor.

 Los desencadenadores DDL y DML se crean, modifican y quitan con una sintaxis
Transact-SQL similar y tienen un comportamiento parecido.
Ejemplo 2

 Utilizar un trigger DML con un mensaje de aviso. El siguiente trigger DML imprime
un mensaje en el cliente cuando alguien intenta agregar o cambiar datos en la tabla
Customer.

CREATE TRIGGER recordatorio1


ON Sales.Customer
AFTER INSERT, UPDATE
AS RAISERROR ('Notify Customer Relations', 16, 10)
GO

También podría gustarte