You are on page 1of 43

BD II (SI 587)

Gatilhos (Triggers)

Prof. Josenildo Silva


jcsilva@ifma.edu.br
Motivação

Algumas rotinas precisam ser


executadas antes ou depois de um
determinado evento no banco de
dados
Motivação

Regras de negócios complexas


precisam ser verificadas a cada
operação do banco de dados
Motivação

Somente com visões, funções e


procedimentos não é possível
realizar nenhuma das duas
situações
TRIGGERS
O que são triggers?

É um conjunto de operações
executadas automaticamente
quando uma alteração é feita em
uma tabela
Execução

É disparada (pelo SGBD) antes ou


depois de um INSERT, UPDATE ou
DELETE
Pode haver até seis triggers por
tabela
Utilização de Triggers

Atender regras de negócios


Verificar a integridade dos dados, pois
é possível fazer uma verificação antes
da inserção do registro
Contornar erros na regra de negócio
do sistema no banco de dados;
Auditar as mudanças nas tabelas.
Exemplos

Aprovar financiamento maiores que


um determinado valor
Atualizar uma tabela de auditoria
após alteração de um registro em
outra tabela.
9
Triggers em SQL

Comando CREATE TRIGGER


Um trigger típico tem três
componentes:
Evento(s)
Condição
Ação
Triggers em SQL

Comando CREATE TRIGGER


Um trigger típico tem três componentes:
Evento(s)
Condição
Ação
Triggers em SQL

Comando CREATE TRIGGER


Um trigger típico tem três componentes:
Evento(s)
Condição
Ação
Acesso a outras tabelas

Uma TRIGGER é sempre associada


a uma tabela, porém os seus
comandos podem acessar dados
de outras tabelas

13
Exemplo de acesso a outras tabelas

Dadas as tabelas
Nota_Fiscal(Num_nota, valor_total)
Produto(Cod_Prod, nome, preço, estoque)
Nota_Prod(Num_nota, Cod_Prod, quantidade)

Pode-se criar uma trigger para a operação de


INSERT na tabela Nota_Prod que atualiza o nível de
estoque do produto vendido

*
Eventos em cascata

Pode-se usar TRIGGERS para


exclusão e atualização em cascata
Se um comando executado violar
uma CONSTRAINT, a TRIGGER não
irá disparar.
*
Restrições

Não são permitidos os seguintes


comandos:
ALTER DATABASE, CREATE DATABASE, DROP
DATABASE, LOAD DATABASE, LOAD LOG,
RESTORE DATABASE, RESTORE LOG,
RECONFIGURE
Palavras chave OLD e NEW

As triggers tem acesso a duas


tabelas em memória referenciadas
pelas palavra chave OLD e NEW
Palavras chave OLD e NEW

:OLD e :NEW (No mysql se omite os dois


pontos)
Quando a operação for de insert temos acesso
apenas a tabela :new
Quando a operação for de update temos
acesso as tabela :old, :new
Quando a operação for de delete temos
acesso apenas a tabela :old
TRIGGERS NO MYSQL
Triggers no MySQL

Será criado uma trigger para cada


evento das tabelas
ENTRADA_PRODUTO e SAIDA_PRODUTO
Nota: o MySQL não suporta múltiplos eventos em uma
mesma trigger
Triggers no MySQL

Padrão de nomeclatura
“trg”+ nome da tabela + id do evento
AI : After Insert (Após Inserção)

AU: After Update (Após Atualização)

AD: After Delete (Após Exclusão)


Triggers no MySQL

Serão criadas as seguintes triggers:


trg_EntradaProduto_AI;
trg_EntradaProduto_AU;
trg_EntradaProduto_AD;
trg_SaidaProduto_AI;
trg_SaidaProduto_AU;
trg_SaidaProduto_AD.
Triggers no MySQL
TRIGGER trg_entradaProduto_AI
DELIMITER $$
CREATE TRIGGER trg_entradaProduto_AI AFTER
INSERT ON entrada_produto
FOR EACH ROW
BEGIN
CALL sp_atualizaEstoque (new.id_produto,
new.qtde,
new.valor_unitario);
END $$
DELIMITER ;
Triggers no MySQL
TRIGGER trg_entradaProduto_AU
DELIMITER $$
CREATE TRIGGER trg_entradaProduto_AU AFTER
UPDATE ON entrada_produto
FOR EACH ROW
BEGIN
CALL sp_atualizaEstoque (new.id_produto,
new.qtde - old.qtde,
new.valor_unitario );
END $$
DELIMITER;
Triggers no MySQL
TRIGGER trg_entradaProduto_AD
DELIMITER $$
CREATE TRIGGER trg_entradaProduto_AU AFTER
DELETE ON entrada_produto
FOR EACH ROW
BEGIN
CALL sp_atualizaEstoque (old.id_produto,
old.qtd * -1,
old.valor_unitario );
END $$
DELIMITER;
Triggers no MySQL
TRIGGER trg_saidaProduto_AI
DELIMITER $$
CREATE TRIGGER trg_saidaProduto_AI AFTER INSERT
ON saida_produto
FOR EACH ROW
BEGIN
CALL sp_atualizaEstoque (new.id_produto,
new.qtde * -1,
new.valor_unitário);
END $$
DELIMITER;
Triggers no MySQL
TRIGGER trg_saidaProduto_AU
DELIMITER $$
CREATE TRIGGER trg_saidaProduto_AU AFTER UPDATE
ON saida_produto
FOR EACH ROW
BEGIN
CALL sp_atualizaEstoque (new.id_produto,
old.qtde - new.qtde,
new.valor_unitario);
END $$
DELIMITER;
Triggers no MySQL
TRIGGER trg_saidaProduto_AD
DELIMITER $$
CREATE TRIGGER trg_saidaProduto_AD AFTER DELETE
ON saida_produto
FOR EACH ROW
BEGIN
CALL sp_atualizaEstoque (old.id_produto,
old.qtde,
old.valor_unitário);
END $$
DELIMITER;
Habilitando e Desabilitando Trigger

Para desabilitar temporariamente uma


trigger:
ALTER TABLE Nome_da_Tabela
DISABLE TRIGGER Nome_da_Trigger

Para habilitar novamente uma trigger:


ALTER TABLE Nome_da_Tabela
ENABLE TRIGGER Nome_da_Trigger

29
TRIGGERS NO ORACLE
Triggers no Oracle

Trigger são blocos PL/SQL


associados com tabelas, views,
esquemas
Triggers no Oracle

Triggers de DML (INSERT, UPDATE e DELETE)


Também: triggers INSTEAD OF para
visões
Triggers de DDL (CREATE, ALTER e DROP)
Triggers de sistema
Triggers de DML - Sintaxe

CREATE [OR REPLACE] TRIGGER <nome>


{timing} event1 | event2 ...
ON {tabela}
[FOR EACH ROW WHEN (predicado)]
{corpo_trigger}
Exemplo 1: Trigger before-statement
CREATE OR REPLACE TRIGGER BEF_STA
BEFORE INSERT ON TB_AUX
BEGIN
DBMS_OUTPUT.PUT_LINE('Inside a BEFORE STMT TRIGGER!');
-- USE THE FOLLOWING LINE TO CANCEL THE ACTION
-- RAISE_APPLICATION_ERROR(-20200,'TEST');
END;

-- TESTING
INSERT INTO TB_AUX VALUES(1,'A')
INSERT INTO TB_AUX VALUES(2,'B')
INSERT INTO TB_AUX VALUES(3,'C')

SELECT * FROM TB_AUX;


Exemplo 2: Trigger before-row
CREATE OR REPLACE TRIGGER BEF_ROW
BEFORE UPDATE OF NAME ON TB_AUX
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('Inside a BEFORE ROW TRIGGER!');
END;

-- TESTING
UPDATE TB_AUX SET NAME = '' WHERE ID = 100;
UPDATE TB_AUX SET ID = 0;
UPDATE TB_AUX SET NAME = '';

SELECT * FROM TB_AUX;


Predicados, e tabelas :old e :new

Predicados indicam o tipo do


trigger
DELETING, INSERTING e UPDATING
Tabelas :old e :new
Em memória, com dados relacionados à
instrução que disparou o trigger
Exemplo 3: Trigger com predicados
CREATE OR REPLACE TRIGGER AFT_STA AFTER INSERT OR UPDATE OR
DELETE ON TB_AUX
BEGIN
IF DELETING THEN
RAISE_APPLICATION_ERROR(-20200,'DELETE CANCELED!');
ELSEIF INSERTING THEN
RAISE_APPLICATION_ERROR(-20200,'INSERT CANCELED!');
ELSEIF UPDATING('NAME') THEN
RAISE_APPLICATION_ERROR(-20200,'UPDATE CANCELED!');
END IF;
END;
-- TESTING -- TESTING
SELECT * FROM TB_AUX; INSERT INTO TB_AUX VALUES(4,'D')

DELETE TB_AUX WHERE ID = 0 UPDATE TB_AUX SET NAME = 'Z'


Exemplo 4: Trigger com :new e :old
CREATE OR REPLACE TRIGGER AFT_ROW
AFTER INSERT OR UPDATE OR DELETE ON TB_AUX
FOR EACH ROW
BEGIN
IF DELETING THEN
DBMS_OUTPUT.PUT_LINE('OLD ID:' || TO_CHAR(:OLD.ID) );
DBMS_OUTPUT.PUT_LINE('OLD NAME:' || TO_CHAR(:OLD.NAME) );
ELSIF INSERTING THEN
DBMS_OUTPUT.PUT_LINE('NEW ID:' || TO_CHAR(:NEW.ID));
DBMS_OUTPUT.PUT_LINE('NEW NAME:' || TO_CHAR(:NEW.NAME));
ELSIF UPDATING('NAME') THEN
DBMS_OUTPUT.PUT_LINE('NEW ID:' || TO_CHAR(:NEW.ID) );
DBMS_OUTPUT.PUT_LINE('OLD ID:' || TO_CHAR(:OLD.ID) );
DBMS_OUTPUT.PUT_LINE('NEW NAME:' || TO_CHAR(:NEW.NAME) );
DBMS_OUTPUT.PUT_LINE('OLD NAME:' || TO_CHAR(:OLD.NAME) );
END IF;
END;
Exemplo 4: cont.

-- TESTING

SELECT * FROM TB_AUX;

DELETE TB_AUX WHERE ID = 0

INSERT INTO TB_AUX VALUES(4,'D')

UPDATE TB_AUX SET NAME = 'Z'


Exemplo 5: cláusula WHEN

CREATE OR REPLACE TRIGGER AFT_WHEN


AFTER INSERT ON TB_AUX
FOR EACH ROW WHEN (NEW.ID = 10)
BEGIN
DBMS_OUTPUT.PUT_LINE('Novo ID igual a 10');
END;

-- TESTE
SELECT * FROM TB_AUX;
INSERT INTO TB_AUX VALUES(9,'M');
INSERT INTO TB_AUX VALUES(10,'N');
INSERT INTO TB_AUX VALUES(11,'O');

DROP TRIGGER AFT_WHEN;


Exemplo 6: cláusula WHEN
CREATE OR REPLACE TRIGGER Print_salary_changes
BEFORE DELETE OR INSERT OR UPDATE ON emp
FOR EACH ROW
WHEN (NEW.EMPNO > 0)
DECLARE sal_diff number;
BEGIN
sal_diff := :NEW.SAL - :OLD.SAL;
dbms_output.put('Old salary: '|| :OLD.sal);
dbms_output.put('New salary: '|| :NEW.sal);
dbms_output.put_line('Diff: '|| sal_diff );
END;
Trigger instead of para Visões
CREATE VIEW VW_AUX AS SELECT * FROM TB_AUX;

CREATE OR REPLACE TRIGGER TR_IO


INSTEAD OF INSERT ON VW_AUX
FOR EACH ROW
BEGIN
INSERT INTO TB_AUX VALUES(:NEW.ID, :NEW.NAME);
END;

-- TESTES
SELECT * FROM VW_AUX;
SELECT * FROM TB_AUX;
INSERT INTO VW_AUX VALUES(99,'W');
SEQUÊNCIA DE DISPARO para triggers no Oracle

BEFORE STATEMENT
BEFORE ROW
AFTER ROW
CONSTRAINTS CHECK
AFTER STATEMENT