› Fóruns › SQL e PL/SQL › Trigger Só Executa Primeiro Bloco do Programa › Trigger Só Executa Primeiro Bloco do Programa
Você não pode usar pragma autonomous transaction para isso, esse recurso não foi criado para contornar ORA-04091 (mutating trigger).
O jeito correto é criar 3 triggers:
– uma before/after each row gravando as linhas afetadas numa nested table de uma package. Vai ser after ou before dependendo do que você quer fazer.
– uma trigger after statement que coleta da nested table o conjunto de linhas afetadas e faz um loop processando sua lógica (no seu caso updates).
– uma trigger para inicializar a nested table e limpá-la antes de cada statement.
No Oracle 11g existe o recurso de compound trigger, onde você faz tudo numa trigger composta, que pode possuir todos os momentos (before/after, for each row/statement). A lógica é a mesma acima.
Aqui tem a cópia do artigo do Tom Kyte solucionando o problema:
http://glufke.net/oracle/viewtopic.php?t=96
Seguem alguns artigos relacionados.
Sobre pragma autonomous transaction:
http://www.orafaq.com/node/1915
Sobre erro de mutating trigger:
http://asktom.oracle.com/pls/asktom/f?p … 9487119866
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0
Connected as fsitja
SQL> create table tabela_1 (numero number, tipo varchar2(10), campo number(10));
Table created
SQL> create table tabela_2 (numero number(10), tipo varchar2(10));
Table created
SQL>
SQL> CREATE OR REPLACE PACKAGE pack_estado_tab_1 IS
2 type t_nt_tabela_1 is table of tabela_1%rowtype;
3 nt_tab_1 t_nt_tabela_1 := t_nt_tabela_1(null);
4 END;
5 /
Package created
SQL>
SQL> CREATE OR REPLACE TRIGGER tg_tab_1_ai_r
2 AFTER INSERT ON tabela_1
3 FOR EACH ROW
4 DECLARE
5 v_rec_tab_1 tabela_1%rowtype;
6 BEGIN
7 pack_estado_tab_1.nt_tab_1.extend;
8 v_rec_tab_1.numero := :new.numero;
9 v_rec_tab_1.tipo := :new.tipo;
10 v_rec_tab_1.campo := :new.campo;
11 pack_estado_tab_1.nt_tab_1(pack_estado_tab_1.nt_tab_1.last) := v_rec_tab_1;
12 END;
13 /
Trigger created
SQL>
SQL> CREATE OR REPLACE TRIGGER tg_tab_1_bi_s
2 AFTER INSERT ON tabela_1
3 BEGIN
4 pack_estado_tab_1.nt_tab_1.delete;
5 END;
6 /
Trigger created
SQL>
SQL> CREATE OR REPLACE TRIGGER tg_tab_1_ai_s
2 AFTER INSERT ON tabela_1
3 BEGIN
4 FOR i IN 1 .. pack_estado_tab_1.nt_tab_1.count
5 LOOP
6 INSERT INTO tabela_2
7 (numero, tipo)
8 VALUES
9 (pack_estado_tab_1.nt_tab_1(i).numero, pack_estado_tab_1.nt_tab_1(i).tipo);
10 UPDATE tabela_1
11 SET campo = 3
12 WHERE numero = pack_estado_tab_1.nt_tab_1(i).numero;
13 END LOOP;
14 END;
15 /
Trigger created
SQL> insert into tabela_1(numero, tipo) values (1, 'A');
1 row inserted
SQL> insert into tabela_1(numero, tipo) values (2, 'B');
1 row inserted
SQL> insert into tabela_1(numero, tipo) values (2, 'C');
1 row inserted
SQL> select * from tabela_1;
NUMERO TIPO CAMPO
1 A 3
2 B 3
2 C 3
SQL> select * from tabela_2;
NUMERO TIPO
1 A
2 B
2 C
SQL> rollback;
Rollback complete
SQL> drop table tabela_1;
Table dropped
SQL> drop table tabela_2;
Table dropped
SQL> drop package pack_estado_tab_1;
Package dropped
SQL>