Olá,
Até o Oracle 11g, não se podia determinar a ordem de execução de triggers do mesmo tipo para uma tabela. Por exemplo, se temos 3 triggers em uma tabela na qual todas são BEFORE INSERT, qual será a ordem de execução das mesmas? A resposta é: impossível determinar, pois se você tiver várias triggers do mesmo tipo na tabela, então o Oracle escolherá uma ordem arbitrária e randômica para executá-las. Então dependendo da regra de negócio existente, isso poderia ser um problema ou não, pois a solução seria criar uma única trigger do tipo em questão e colocar toda a regra de negócio (PL/SQL) nela. A desvantagem nesse caso seria apenas de cunho administrativo e de manutenção, pois a trigger poderia ficar imensa, complexa e de difícil compreensão.
Na minha visão, a vantagem de se ter mais de uma trigger seria a de trazer mais praticidade e modularidade de forma a separar a regra de negócio de acordo com o objetivo de cada uma, além de trazer uma certa flexibilidade na hora realizar manutenções no código. Imagina um cenário onde existe uma única trigger que, além de realizar grande parte da regra de negócio, ainda realiza operações para geração de logs de transação. Veja a flexibilidade se criássemos 2 triggers: uma para a regra de negócio em si e outra para geração de logs de transação. Alguém um dia poderia sugerir: "A rotina está muito lenta hoje, acho melhor desabilitarmos a trigger que realiza a geração dos logs de transação" Fácil não?
Na minha visão, a vantagem de se ter mais de uma trigger seria a de trazer mais praticidade e modularidade de forma a separar a regra de negócio de acordo com o objetivo de cada uma, além de trazer uma certa flexibilidade na hora realizar manutenções no código. Imagina um cenário onde existe uma única trigger que, além de realizar grande parte da regra de negócio, ainda realiza operações para geração de logs de transação. Veja a flexibilidade se criássemos 2 triggers: uma para a regra de negócio em si e outra para geração de logs de transação. Alguém um dia poderia sugerir: "A rotina está muito lenta hoje, acho melhor desabilitarmos a trigger que realiza a geração dos logs de transação" Fácil não?
No mais, neste artigo irei demonstrar que com o Oracle 11g podemos determinar a ordem de execução das triggers de uma tabela que são de um mesmo tipo. Na criação de uma trigger no Oracle 11g, existe uma nova cláusula chamada "follows" que nos permitirá definir a ordem de execução das mesmas.
No primeiro exemplo abaixo, irei criar 3 triggers do tipo BEFORE INSERT sem definir uma ordem de execução.
C:\>sqlplus scott/tiger
SQL*Plus: Release 11.2.0.1.0 Production on Qua Ago 3 21:34:36 2011
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> create table t1 (id number);
Tabela criada.
SQL> create or replace trigger trg_teste_01
2 before insert on t1
3 for each row
4 begin
5 dbms_output.put_line('trigger trg_teste_01');
6 end;
7 /
Gatilho criado.
SQL> create or replace trigger trg_teste_02
2 before insert on t1
3 for each row
4 begin
5 dbms_output.put_line('trigger trg_teste_02');
6 end;
7 /
Gatilho criado.
SQL> create or replace trigger trg_teste_03
2 before insert on t1
3 for each row
4 begin
5 dbms_output.put_line('trigger trg_teste_03');
6 end;
7 /
Gatilho criado.
Após a criação da tabela e das triggers, irei inserir um registro na tabela T1.
SQL> set serveroutput on
SQL> insert into t1 values (1);
trigger trg_teste_03
trigger trg_teste_02
trigger trg_teste_01
1 linha criada.
Perceberam que a trigger trg_teste_03 foi acionada primeiro? Quem garante que a mesma será executada primeiro na próxima vez? Bom, no segundo exemplo abaixo irei criar novamente as triggers só que, agora, definindo a ordem de execução: trg_teste_01, depois trg_teste_02 e depois trg_teste_03.
SQL> create or replace trigger trg_teste_01
2 before insert on t1
3 for each row
4 begin
5 dbms_output.put_line('trigger trg_teste_01');
6 end;
7 /
Gatilho criado.
SQL> create or replace trigger trg_teste_02
2 before insert on t1
3 for each row
4 follows trg_teste_01
5 begin
6 dbms_output.put_line('trigger trg_teste_02');
7 end;
8 /
Gatilho criado.
SQL> create or replace trigger trg_teste_03
2 before insert on t1
3 for each row
4 follows trg_teste_02
5 begin
6 dbms_output.put_line('trigger trg_teste_03');
7 end;
8 /
Gatilho criado.
SQL> insert into t1 values (2);
trigger trg_teste_01
trigger trg_teste_02
trigger trg_teste_03
1 linha criada.
Pronto. Podemos ver que as mesmas foram acionadas de acordo com a ordem que eu havia definido anteriormente. Poderíamos inclusive desabilitar uma das triggers que não haveria problema nenhum:
SQL> alter trigger trg_teste_02 disable;
Gatilho alterado.
SQL> insert into t1 values (3);
trigger trg_teste_01
trigger trg_teste_03
1 linha criada.
Agora, caso alguma trigger que é dependente de outra for dropada, aí sim teremos problemas pois não conseguiremos realizar algumas operações até que o problema seja sanado.
SQL> drop trigger trg_teste_02;
Gatilho eliminado.
SQL> select object_name,status from user_objects where object_type='TRIGGER';
OBJECT_NAME STATUS
------------------------------ -------
TRG_TESTE_01 VALID
TRG_TESTE_03 INVALID
SQL> insert into t1 values (3);
insert into t1 values (3)
*
ERRO na linha 1:
ORA-04045: erros durante a recompilação/revalidação de SCOTT.TRG_TESTE_03
ORA-04098: gatilho 'SCOTT.TRG_TESTE_03' é inválido e a revalidação falhou
SQL> drop table t1;
drop table t1
*
ERRO na linha 1:
ORA-00604: ocorreu um erro no nível 1 SQL recursivo
ORA-04045: erros durante a recompilação/revalidação de SCOTT.TRG_TESTE_03
ORA-04098: gatilho 'SCOTT.TRG_TESTE_03' é inválido e a revalidação falhou
SQL> alter trigger trg_teste_03 disable;
Gatilho alterado.
SQL> insert into t1 values (4);
trigger trg_teste_01
1 linha criada.
SQL> drop table t1;
Tabela eliminada.
6 comentários:
Olá Eduardo!! Eu tinha a impressão anteriormente que a ordem de execução era definida pelo id do objeto... lembro que em bases de desenvolvimento ou de produção qdo eram rodados os scripts funcionavam na ordem dos mesmo, porém no caso de um import novo, essa ordem não era mais respeitada talvez pela criação do import ser diferente...Grande material
Abraços
Fabio Ishii
E ai Legatti!
Maneiro essa implementação a partir do oracle 11g.Parabéns mais uma vez por um post de ótima qualidade.
Emerson
DBA Jr
Olá Fábio,
Tudo bem?? Poisé, realmente não haveria como garantir isso, ainda mais após uma importação ;-)
Abraços e até mais...
Olá Emerson,
Esta new feature do 11g veio mesmo na hora certa ;-)
Abraços e até mais...
Olá Eduardo !
Recurso interessante... Pra falar a verdade não sabia que podia criar varias trigger pro mesmo evento...Pensei que fosse possível apenas uma... Bom, agora eu sei que até pra ordenar a execução...
Att,
Sakamoto
MyTraceLog - Registro de um DBA
http://mytracelog.blogspot.com
Realmente muito interessante essa feature, mais uma vez parabéns!!
Um Abraço
Postar um comentário