Ainda recomendaria o a utilização de uma transação autonoma. O problema de trigger mutante tambem é propagado em referências cíclicas, para o caso em questão não vejo grandes problemas de utilizar a transação autonoma.
Atenciosamente, Caio Spadafora. ________________________________ De: Sérgio Luiz Rodrigues Chaves <sergio.cha...@elumini.com.br> Para: oracle_br@yahoogrupos.com.br Enviadas: Quarta-feira, 25 de Novembro de 2009 11:59:13 Assunto: RES: [oracle_br] Trigger mutanting Debby, Vou listar o procedimento básico para resolver esse problema: 1) Tenho a tabela funcionário com a seguinte estrutura: CREATE TABLE FUNC ( CD_MAT NUMBER(3) NOT NULL PRIMARY KEY, NR_GIT NUMBER(2), VL_SAL NUMBER(9,2) 2) Tenho uma trigger para atualizar o salário do funcionário. CREATE OR REPLACE TRIGGER checa_salario BEFORE UPDATE OF vl_sal, nr_git ON FUNC FOR EACH ROW WHEN (NEW.nr_git < 56) DECLARE salario_minimo NUMBER(5) := 0; salario_maximo NUMBER(5) := 0; faixa EXCEPTION; negativo EXCEPTION; BEGIN SELECT MIN(vl_sal), Max(vl_sal) INTO salario_minimo, salario_maximo FROM FUNC WHERE nr_git = :new.nr_git; IF (:NEW.vl_sal < salario_minimo OR :NEW.vl_sal > salario_maximo) THEN RAISE faixa; ELSIF (:NEW.VL_SAL < :OLD.vl_sal) THEN RAISE negativo; END IF; EXCEPTION WHEN faixa THEN RAISE_APPLICATION_ ERROR (-20225, 'Salário fora da faixa'); WHEN negativo THEN RAISE_APPLICATION_ ERROR (-20230, 'Incremento negativo'); END; Que quando executo dá erro de "multante", pois estou realizando uma consulta na mesma tabela que estou atualizando. 3) Resolvendo.. .. Criei uma tabela temporária com a mesma estrutura de FUNC de nome TFUNC_MUT. DROP TABLE TFUNC_MUT; CREATE TABLE TFUNC_MUT ( CD_MAT NUMBER(3) NOT NULL PRIMARY KEY, NR_GIT NUMBER(2), VL_SAL NUMBER(9,2), NR_ORDEM NUMBER,--- nova coluna STATUS VARCHAR2(10) --- nova coluna ) DROP SEQUENCE ORDEM / CREATE SEQUENCE ORDEM ORDER START WITH 1 NOCYCLE / 4) Recrio a trigger gravando na tabela temporária CREATE OR REPLACE TRIGGER checa_salario BEFORE UPDATE OF vl_sal, nr_git ON FUNC FOR EACH ROW WHEN (NEW.nr_git < 56) DECLARE salario_minimo NUMBER(5) := 0; salario_maximo NUMBER(5) := 0; qtd NUMBER; negativo EXCEPTION; BEGIN IF (:NEW.VL_SAL < :OLD.vl_sal) THEN RAISE negativo; ELSE SELECT COUNT(*) INTO qtd FROM tfunc_mut where cd_mat = :new.cd_mat; IF qtd = 0 THEN INSERT INTO TFUNC_MUT (cd_mat, vl_sal, nr_git, nr_ordem, status) VALUES (:NEW.cd_mat, :NEW.vl_sal, :NEW.nr_git, ordem.nextval, 'VALID'); :NEW.vl_sal := :OLD.vl_sal; end if; END IF; EXCEPTION WHEN negativo THEN RAISE_APPLICATION_ ERROR (-20230, 'Incremento negativo'); END; 5) Crio nova trigger CREATE OR REPLACE TRIGGER checa_salario_ mut AFTER UPDATE OF vl_sal, nr_git ON FUNC DECLARE cursor wc is SELECT * FROM tfunc_mut WHERE status = 'VALID' ORDER BY NR_ORDEM FOR UPDATE; salario_minimo NUMBER(5) := 0; salario_maximo NUMBER(5) := 0; faixa EXCEPTION; TYPE TIPO_MUT IS TABLE OF TFUNC_MUT%ROWTYPE INDEX BY BINARY_INTEGER; TABMUT TIPO_MUT; I NUMBER := 0; BEGIN FOR wr IN wc LOOP SELECT MIN(vl_sal), MAX(vl_sal) INTO salario_minimo, salario_maximo FROM func WHERE nr_git = wr.nr_git; IF wr.vl_sal < salario_minimo OR wr.vl_sal > salario_maximo THEN RAISE faixa; ELSE I := I + 1; TABMUT(I) := WR; UPDATE tfunc_mut SET status = 'INVALID'; END IF; END LOOP; FOR J IN 1..I LOOP UPDATE func SET vl_sal = TABMUT(J).vl_ sal, nr_git = TABMUT(J).nr_ git WHERE cd_mat = TABMUT(J).cd_ mat; END LOOP; IF I > 0 THEN DELETE FROM tfunc_mut; END IF; EXCEPTION WHEN faixa THEN DELETE FROM tfunc_mut; RAISE_APPLICATION_ ERROR (-20230, 'Salário fora da faixa'); END; / Verifique se os códigos acima lhe ajudam para resolver seu problema. Boa sorte. Atenciosamente, Sérgio Chaves. ____________ _________ _________ __ De: oracle...@yahoogrup os.com.br [mailto:oracle...@yahoogrup os.com.br] Em nome de Sergio Lucchini Enviada em: quarta-feira, 25 de novembro de 2009 10:58 Para: oracle...@yahoogrup os.com.br Assunto: RES: [oracle_br] Trigger mutanting Isso ocorre quando vc precisa acessa a tabela onde esta a trigger. Vc pode declarar a sua trigger como Pragma Autonomous_Transact ion para eliminar esse erro. Exemplo: CREATE OR REPLACE TRIGGER nome_trigger AFTER UPDATE ON nome_tabela REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW DECLARE Pragma Autonomous_Transact ion; BEGIN ........ Sergio Lucchini ____________ _________ _________ __ De: oracle...@yahoogrup os.com.br <mailto:oracle_ br%40yahoogrupos .com.br> [mailto:oracle...@yahoogrup os.com.br <mailto:oracle_ br%40yahoogrupos .com.br> ] Em nome de Débora Acácio Enviada em: quarta-feira, 25 de novembro de 2009 09:41 Para: Grp Oracle Assunto: [oracle_br] Trigger mutanting Olá Estou tendo um problema numa trigger que estou alterando... . está dando erro de trigger mutanting... alguém poderia me ajudar ? Grata Debby :) ____________ _________ _________ _________ _________ _________ _ Veja quais são os assuntos do momento no Yahoo! +Buscados http://br.maisbusca dos.yahoo. com <http://br.maisbusca dos.yahoo. com> [As partes desta mensagem que não continham texto foram removidas] No virus found in this incoming message. Checked by AVG - www.avg.com Version: 8.5.423 / Virus Database: 270.14.81/2524 - Release Date: 11/24/09 19:37:00 [As partes desta mensagem que não continham texto foram removidas] [As partes desta mensagem que não continham texto foram removidas] ____________________________________________________________________________________ Veja quais são os assuntos do momento no Yahoo! +Buscados http://br.maisbuscados.yahoo.com [As partes desta mensagem que não continham texto foram removidas]