wallter 0 Denunciar post Postado Dezembro 1, 2014 Bom dia Estou com problema e não consigo resolver. Criei uma trigger para monitorar uma tabela de pedidos, quando acontece o insert, ela deleta os registro inserido e insere os novos. Então minha trigger monitora e faz o insert na mesma tabela. Estou erro de deadlock, quando tento fazer qualquer insert nesta tabela. A primeira parte da trigger verifica verifica se pedido existe em uma outra tabela, se existir a trigger executa. CREATE OR REPLACE TRIGGER TG_GRADE_ESTOQUE AFTER INSERT OR DELETE OR UPDATE ON APROV_PED_SUP FOR EACH ROW DECLARE existe_registro NUMBER(1); Pragma Autonomous_Transaction; BEGIN IF INSERTING THEN BEGIN SELECT 1 into existe_registro from VI_VERIFICA_PEDIDO_ESTOQUE where num_pedido = :NEW.NUM_PEDIDO; EXCEPTION WHEN OTHERS THEN existe_registro := 0; END; if existe_registro = 1 THEN DELETE FROM APROV_PED_SUP WHERE NUM_PEDIDO = :NEW.NUM_PEDIDO AND NUM_VERSAO_PEDIDO = :NEW.NUM_VERSAO_PEDIDO; BEGIN INSERT INTO APROV_PED_SUP SELECT A.COD_EMPRESA, B.NIVEL, A.NUM_PEDIDO, A.NUM_VERSAO, 1 VERSAO_GRADE, CASE WHEN B.NIVEL ='CO' THEN D.LOGIN ELSE NULL END NOME_USUARIO_APROV, CASE WHEN B.NIVEL ='CO' THEN TO_DATE(SYSDATE,'DD/MM/YYYY') ELSE NULL END DATA_APROVACAO, CASE WHEN B.NIVEL ='CO' THEN TO_CHAR(SYSDATE,'HH24:MI:SS') ELSE NULL END HOR_APROVACAO, D.LOGIN USUARIO_INCLUSAO, TO_DATE(SYSDATE,'DD/MM/YYYY') DAT_INCLUSAO, TO_CHAR(SYSDATE,'HH24:MI:SS') HOR_INCLUSAO FROM PEDIDO_SUP A INNER JOIN GRADE_ESTOQUE B ON(A.VAL_TOT_PED >= B.VALOR_INI AND A.VAL_TOT_PED <= B.VALOR_FIM) INNER JOIN ORDEM_SUP C ON(A.NUM_PEDIDO = C.NUM_PEDIDO) INNER JOIN COMPRADOR D ON(C.COD_COMPRADOR = D.COD_COMPRADOR AND D.COD_EMPRESA =01) WHERE A.NUM_PEDIDO =:NEW.NUM_PEDIDO AND A.NUM_VERSAO =:NEW.NUM_VERSAO_PEDIDO GROUP BY A.COD_EMPRESA, B.NIVEL, A.NUM_PEDIDO, A.NUM_VERSAO, D.LOGIN; END; END IF; END IF; END; Compartilhar este post Link para o post Compartilhar em outros sites
Motta 645 Denunciar post Postado Dezembro 1, 2014 Despulpe mas qual seria a razão deste processo ? Você poderia obter valores por query e atribuí-los aos campos da tabela da trigger , mas a trigger teria de ser de BEFORE. Mas o processo me parece estranho , deletar para depois inserir. Outra observação : se só vai tratar o INSERT a trigger só precisa ser de INSERT ----- Ficaria algo assim CREATE OR REPLACE TRIGGER TG_GRADE_ESTOQUE BEFORE INSERT ON APROV_PED_SUP FOR EACH ROW DECLARE existe_registro NUMBER(1); Pragma Autonomous_Transaction; --defina aqui as variaveis VS_COD_EMPRESA PEDIDO_SUP.COD_EMPRESA%type; VS_NIVEL tipo etc VS_NUM_PEDIDO tipo etc VS_NUM_VERSAO tipo etc VS_VERSAO_GRADE tipo etc VS_NOME_USUARIO_APROV tipo etc VS_DATA_APROVACAO tipo etc VS_HOR_APROVACAO tipo etc VS_USUARIO_INCLUSAO tipo etc VS_DAT_INCLUSAO tipo etc VS_HOR_INCLUSAO tipo etc BEGIN IF INSERTING THEN BEGIN SELECT 1 into existe_registro from VI_VERIFICA_PEDIDO_ESTOQUE where num_pedido = :NEW.NUM_PEDIDO; EXCEPTION WHEN OTHERS THEN existe_registro := 0; END; if existe_registro = 1 THEN BEGIN SELECT A.COD_EMPRESA, B.NIVEL, A.NUM_PEDIDO, A.NUM_VERSAO, 1 VERSAO_GRADE, CASE WHEN B.NIVEL ='CO' THEN D.LOGIN ELSE NULL END NOME_USUARIO_APROV, CASE WHEN B.NIVEL ='CO' THEN TO_DATE(SYSDATE,'DD/MM/YYYY') ELSE NULL END DATA_APROVACAO, CASE WHEN B.NIVEL ='CO' THEN TO_CHAR(SYSDATE,'HH24:MI:SS') ELSE NULL END HOR_APROVACAO, D.LOGIN USUARIO_INCLUSAO, TO_DATE(SYSDATE,'DD/MM/YYYY') DAT_INCLUSAO, TO_CHAR(SYSDATE,'HH24:MI:SS') HOR_INCLUSAO INTO VS_COD_EMPRESA, VS_NIVEL, VS_NUM_PEDIDO, VS_NUM_VERSAO, VS_VERSAO_GRADE, VS_NOME_USUARIO_APROV, VS_DATA_APROVACAO, VS_HOR_APROVACAO, VS_USUARIO_INCLUSAO, VS_DAT_INCLUSAO, VS_HOR_INCLUSAO FROM PEDIDO_SUP A INNER JOIN GRADE_ESTOQUE B ON(A.VAL_TOT_PED >= B.VALOR_INI AND A.VAL_TOT_PED <= B.VALOR_FIM) INNER JOIN ORDEM_SUP C ON(A.NUM_PEDIDO = C.NUM_PEDIDO) INNER JOIN COMPRADOR D ON(C.COD_COMPRADOR = D.COD_COMPRADOR AND D.COD_EMPRESA =01) WHERE A.NUM_PEDIDO =:NEW.NUM_PEDIDO AND A.NUM_VERSAO =:NEW.NUM_VERSAO_PEDIDO GROUP BY A.COD_EMPRESA, B.NIVEL, A.NUM_PEDIDO, A.NUM_VERSAO, D.LOGIN; END; atribui ao new :new.NUM_PEDIDO := vs_NUM_PEDIDO; demais campos END IF; END IF; END; Compartilhar este post Link para o post Compartilhar em outros sites
wallter 0 Denunciar post Postado Dezembro 1, 2014 Bom dia Motta A razão é, contornar algo que aplicação não resolve para o momento. Aplicação faz o insert de 4 linhas, a trigger deleta as 4 e faz o insert de 3 linhas diferentes. Acredito que a solução proposta por você só pode inserir uma linha correto? Compartilhar este post Link para o post Compartilhar em outros sites
Motta 645 Denunciar post Postado Dezembro 1, 2014 Acho que trigger não vai resolver isto pois se está deletando e inserindo na mesma tabelae um número de registros diferentes Talvez , e digo talvez pois nunca fiz nada parecido uma TRIGGER de INSTEND OF resolva , mas só testando. Mas para isto acho que a aplicação deveria trabalhar com uma trigger e não a tabela em si , o que pode ser um complicador. O correto seria consertar a aplicação , é tão complicado assim !? ======================================================= Outra solução seria uma procedure que faria esta correção um JOB schedullado rodando de x em x minutos faria a correção. Compartilhar este post Link para o post Compartilhar em outros sites
wallter 0 Denunciar post Postado Dezembro 4, 2014 Bom dia Motta, Consegui fazer uma alteração na aplicação, e agora a trigger só precisa excluir uma das três linhas que são inseridas. Fiz a trigger, mas por algum motivo que não entendo ela não esta excluindo. Se rodo a query direto ela exclui a terceira linha perfeitamente, mas na trigger não vai. CREATE OR REPLACE TRIGGER TG_GRADE_ESTOQUE_03 AFTER INSERT ON APROV_PED_SUP FOR EACH ROW DECLARE Pragma Autonomous_Transaction; cursor c1 is select COD_NIVEL_AUTORID, NUM_PEDIDO, NUM_VERSAO_PEDIDO from LOGIX.APROV_PED_SUP WHERE COD_NIVEL_AUTORID NOT IN (SELECT B.NIVEL FROM LOGIX.PEDIDO_SUP A INNER JOIN LOGIX.GRADE_ESTOQUE B ON(A.VAL_TOT_PED >= B.VALOR_INI AND A.VAL_TOT_PED <= B.VALOR_FIM) INNER JOIN LOGIX.ORDEM_SUP C ON(A.NUM_PEDIDO = C.NUM_PEDIDO) INNER JOIN LOGIX.COMPRADOR D ON(C.COD_COMPRADOR = D.COD_COMPRADOR AND D.COD_EMPRESA =01) WHERE A.NUM_PEDIDO =:NEW.NUM_PEDIDO AND A.NUM_VERSAO =:NEW.NUM_VERSAO_PEDIDO GROUP BY A.COD_EMPRESA, B.NIVEL, A.NUM_PEDIDO, A.NUM_VERSAO, D.LOGIN); BEGIN for r1 in c1 loop DELETE FROM LOGIX.APROV_PED_SUP WHERE NUM_PEDIDO = r1.NUM_PEDIDO AND NUM_VERSAO_PEDIDO = r1.NUM_VERSAO_PEDIDO AND COD_NIVEL_AUTORID = r1.COD_NIVEL_AUTORID; COMMIT; END LOOP; END; Compartilhar este post Link para o post Compartilhar em outros sites
Motta 645 Denunciar post Postado Dezembro 4, 2014 Qual o problema em alterar a aplicação para não inserir as linhas indevidas ? Por trigger , excluído a própria operação acho que não rola, mas só pesquisando. Compartilhar este post Link para o post Compartilhar em outros sites