Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

Diego Farias

Erro: Trigger que executa um INSERT e depois UPDATE no mesmo bloco PL/SQL

Mensagens Recomendadas

Diego Farias

Boa tarde pessoal,

Tenho uma trigger para não permitir a atualização se o preço for negativo e registrar na tabela valor_produto. A trigger é dispara na tabela produto.

Segue o código para entender melhor :

CREATE TABLE PRODUTO (
CODIGO NUMBER(4),
VALOR NUMBER(7,2));
INSERT INTO produto VALUES (1001, 2.55);
INSERT INTO produto VALUES (1002, 3.25);
INSERT INTO produto VALUES (1003, 2.85);
-- Criar outra tabela denominada VALOR_PRODUTO:
CREATE TABLE VALOR_PRODUTO (
CODIGO NUMBER(4),
VALOR_ANTERIOR NUMBER(7,2),
VALOR_NOVO NUMBER(7,2));
CREATE OR REPLACE TRIGGER VERIFICA_VALOR
BEFORE UPDATE OF VALOR ON PRODUTO
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
WHEN( NEW.VALOR < 0 )
BEGIN
 INSERT INTO VALOR_PRODUTO
 VALUES(:OLD.CODIGO, :OLD.VALOR, :NEW.VALOR);
 UPDATE PRODUTO
 SET VALOR = :OLD.VALOR
 WHERE CODIGO = :NEW.CODIGO;
END VERIFICA_VALOR;
/
UPDATE PRODUTO SET VALOR = -701.03 WHERE CODIGO = 1003;
SELECT * FROM PRODUTO;
SELECT * FROM VALOR_PRODUTO;

O erro acontece quando o update é executado:

Erro a partir da linha : 84 no comando -

UPDATE PRODUTO SET VALOR = -701.03 WHERE CODIGO = 1003

Relatório de erros -

Erro de SQL: ORA-04091: a tabela SYSTEM.PRODUTO é mutante; talvez o gatilho/função não possa localizá-la

ORA-06512: em "SYSTEM.VALORPRODUTO_BEFORE_UPDATE", line 4

ORA-04088: erro durante a execução do gatilho 'SYSTEM.VALORPRODUTO_BEFORE_UPDATE'

ORA-06512: em "SYSTEM.PRODUTO_BEFORE_UPDATE", line 9

ORA-04088: erro durante a execução do gatilho 'SYSTEM.PRODUTO_BEFORE_UPDATE'

04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"

*Cause: A trigger (or a user defined plsql function that is referenced in

this statement) attempted to look at (or modify) a table that was

in the middle of being modified by the statement which fired it.

*Action: Rewrite the trigger (or function) so it does not read that table.

Também tentei criar duas triggers, que quando a tabela produto for atualizada com valor negativo, ela dispara a trigger1 e inseri dados na tabela valor_produto, que dispara a trigger2 assim que o INSERT é feito e faz um update na tabela produto para voltar ao valor original, mas não deu certo.

Segue código:

CREATE OR REPLACE TRIGGER produto_before_update
BEFORE UPDATE
ON PRODUTO
FOR EACH ROW
DECLARE
v_username varchar2(10);
BEGIN
IF :NEW.VALOR < 0 THEN
 -- Find username of person performing UPDATE on the table
 SELECT user INTO v_username FROM dual;
 INSERT INTO VALOR_PRODUTO
 VALUES(:OLD.CODIGO, :OLD.VALOR, :NEW.VALOR, v_username, sysdate);	
 END IF;
END;
/
CREATE OR REPLACE TRIGGER valorProduto_before_update
AFTER INSERT
ON VALOR_PRODUTO
FOR EACH ROW
BEGIN
 IF :NEW.VALOR_NOVO < 0 THEN
 UPDATE PRODUTO
 SET VALOR = OLD.VALOR_ANTERIOR
 WHERE CODIGO = :NEW.CODIGO;	
END IF;
END;
/
SELECT * FROM PRODUTO;
UPDATE PRODUTO SET VALOR = -701.03 WHERE CODIGO = 1003;
SELECT * FROM VALOR_PRODUTO;
SELECT * FROM PRODUTO;

Li nesse fórum http://www.techonthenet.com/oracle/errors/ora04091.php que isso e um erro da oracle, mas não estou sabendo resolver alguém pode ajudar. ?

Obrigado

Editado por Diego Farias

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
PaisNeto

Bom dia,

Repara numa coisa, tu estás a fazer um update a um registo e nesse update dizes para fazer outro update, antes do primeiro ser feito...

Que é o que te diz o link que tens aí

"When you create a trigger against a table, you can't modify/query that table until the trigger/function has completed."

Tu fazes o update à tabela a partir de onde, forms, apex?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.