Trigger compila sem erros, mas não executa

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
lavreh
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Sex, 19 Ago 2011 2:24 am
Localização: Magé - RJ

Salve!
Estou no meio do meu aprendizado sobre PL/SQL, e tenho curtido bastante o que tenho visto.
Neste momento pretendo criar uma trigger que após a inserção de um novo empregado, compare o seu salário com o de seu gerente e, caso seja maior, atualize-o igualando ao do gerente.
Mas tenho obtido o seguinte erro:
UNESA@XE > insert into emp(empno, ename,mgr) values(7788, 'TESTE2', 7902);
insert into emp(empno, ename,mgr) values(7788, 'TESTE2', 7902)
*
ERROR at line 1:
ORA-04091: table UNESA.EMP is mutating, trigger/function may not see it
ORA-06512: at "UNESA.COMPSAL", line 6
ORA-04088: error during execution of trigger 'UNESA.COMPSAL'
Segue o código da trigger...

Selecionar tudo

CREATE OR REPLACE TRIGGER compsal
AFTER INSERT
ON emp
FOR EACH ROW

DECLARE
	v_salemp NUMBER(7,2);
	v_salmgr NUMBER(7,2);

BEGIN
	SELECT e.sal INTO v_salemp
	FROM emp e JOIN emp g ON e.mgr = g.empno
	WHERE :NEW.empno = e.empno;
	
	SELECT g.sal INTO v_salmgr
	FROM emp e JOIN emp g ON e.mgr = g.empno
	WHERE :NEW.mgr = e.mgr;
	
	IF v_salemp > v_salmgr THEN
		UPDATE emp
			SET sal = v_salmgr
			WHERE empno = :NEW.empno;
	END IF;
END;
/
ishii
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 82
Registrado em: Ter, 28 Dez 2010 7:41 pm
Localização: São Paulo - SP

Olá,

A trigger mutating ocorre pelo fato de você tentar fazer um update na mesma tabela da trigger que a levaria a entrar num "loop". A melhor solução seria substituir com no new:

Selecionar tudo

IF v_salemp > v_salmgr THEN
      :new.sal = v_salmgr;
END IF;
[]s Ishii
lavreh
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Sex, 19 Ago 2011 2:24 am
Localização: Magé - RJ

Selecionar tudo

IF v_salemp > v_salmgr THEN
	DBMS_Output.Put_Line('Salário maior que o do gerente');
END IF;
Alterei o código, substituindo a parte que atualizaria a tabela, pelo trecho acima que simplesmente imprime no console caso o salário do empregado seja maior.

Porém me parece que o trecho que obtém o salário do gerente continua acusando mutating...

Selecionar tudo

SELECT g.sal INTO v_salmgr
	FROM emp e JOIN emp g ON e.mgr = g.empno
	WHERE e.empno = :NEW.empno;
ishii, tentei uma solução baseada no mesmo princípio da dica que me passou, mas não consegui...

[]'s
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE

Se você executar um select na tabela que ativa a trigger, como no caso, você vai sempre ter esse erro de mutante.
Dependendo das versão do teu banco existe estratégias diferentes para seu problema, como pode ver em:
http://decipherinfosys.wordpress.com/20 ... esolve-it/

Porém, trigger é a última das últimas opções. Se é para estudo tudo bem entender o funcionamento, mas evite.
O ideal seria sua aplicação de aplicação fazer a regra do negócio e já inserir o empregado com o salário adequado.
Manter um sistema orientado a trigger é uma dor de cabeça sensacional......
diego_amoroso
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 17
Registrado em: Qua, 07 Jul 2010 2:53 pm
Localização: Americana - SP
Diego Amoroso
Programador pl/sql
diego.amoroso@yahoo.com.br

Pesquise sobre a função: PRAGMA AUTONOMOUS_TRANSACTION
Ao executar uma trigger com essa função declarada é criado uma nova sessão virtual onde será executado seu select fazendo com que o erro de trigger mutante não ocorra e você consiga realizar o select e posteriormente o update.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Google Adsense [Bot] e 2 visitantes