Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá a todos, sou iniciante em oracle. Estou usando como linguagem o Delphi. Estou tentando colocar todas as regras gerenciais dentro do banco e me deparei com um problema. Acontece que tenho uma tabela pai (produto) e uma tabela filho (lote_produto), fiz uma trigger que dispara após deletar uma linha da tabela lote_produto, ele verifica se existe mais alguma linha daquele produto na lote_produto, caso não exista deve apagar a linha da tabela produto (pai), acontece que quando vou verificar se existe mais linhas da lote_produto ele dá erro de "mutanting", se coloca o "Pragma Autonomous_Transaction" ele até passa mas quando vai apagar a linha da produto dá erro de "deadlock", criei uma view para fazer este select e continuou com o erro de mutating, criei uma procedure para fazer o delete e continuou com o deadlock, não quero levar esta rotina para dentro do programa pois quero ter certeza da integridade dos dados. Alguem teria alguma sugestão para resolver este problema?
Obrigado, segue o codigo :
create or replace trigger TG_TESTE
after delete on lote_produto
for each row
declare
V_QTDE NUMBER(10,2);
Pragma Autonomous_Transaction;
begin
begin
SELECT COUNT(1) INTO V_QTDE FROM LOTE_PRODUTO
WHERE PRODUTO_LOTE_ID = :OLD.PRODUTO_LOTE_ID;
EXCEPTION WHEN NO_DATA_FOUND THEN
V_QTDE := 0;
END;
IF V_QTDE =0 THEN
DELETE FROM PRODUTO
WHERE PRODUTO_LOTE_ID = :OLD.PRODUTO_LOTE_ID;
END IF;
end TG_TESTE;
Não tem um modo simples de evitar a "tabela mutante".
Tente fazer o seguinte : faça a trigger de statement ao invés de for each row.
A trigger de statement é executada após o fim da instrução, por ser de instrução não existem as variáveis new/old.
Verifique nesta trigger se existe registro "pai" sem "filho" e aí faça a deleção, esta verificação deve ser para toda a tabela e não apenas para o que foi deletado.
Esta trigger pode tornar a transação lenta, pois um delete de uma linha fará uma leitura na tabela toda.
Solução possível, criar uma procedura que faz esta limpeza é chamá-la pela aplicação.
--
Veja também :
Qual a opção de ON DELETE da tabela "pai" em relação à "filho" pois se está com ON DELETE CASCADE a delação da trigger faz a deleção em cascata que chama a trigger de forma recursiva, uma solução e usar ON DELETE SET NULL ou RESTRICT.
Para mais detalhes.
Espero ter ajudado.