Trigger utilizando Autonomous_Transaction

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
Freidinger
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 5
Registrado em: Qua, 30 Nov 2011 2:10 pm

Olá pessoas,

Primeiramente, aviso que sou novo em PL SQL, então nem engatinhando ainda estou.
Peguei um teste por aqui na empresa onde estou que me pediu para resolver o seguinte problema, uma trigger.
Esta trigger, dispara quando eu deleto informações de uma linha.
Esse problema, eu já consegui resolver via view, utilizando INSTEAD OF.
Consegui deletar a linha sem problemas.
O que acontece agora é que meu superior disse que ainda há 3 formas de resolver isso.
A primeira seria essa via view.
A segunda, eu pesquisei e encontrei uma função chamada PRAGMA AUTONOMOUS_TRANSACTION.

Vi em vários fóruns que depende para o que eu vou utilizar, e depende muito, melhor utilizar de outra forma.

De qualquer forma, é uma base de teste que estou utilizando aqui e gostaria de ver o que realmente acontece e o que realmente faz esse comando.

Minha trigger está desta forma:

Selecionar tudo

CREATE OR REPLACE TRIGGER rcf_trg_exc_lin_decl
AFTER DELETE
ON imp_declaracoes_lin
FOR EACH ROW
DECLARE

PRAGMA AUTONOMOUS_TRANSACTION;

  CURSOR cur_linha_decl (pn_declaracao_lin_id
  imp_declaracoes_lin.declaracao_lin_id%TYPE) IS
      SELECT qtde  
      FROM imp_declaracoes_lin
      WHERE declaracao_lin_id = pn_declaracao_lin_id;

  vn_tp_declaracao_id   imp_declaracoes.tp_declaracao_id%TYPE;
  você_dsi                imp_declaracoes.dsi%TYPE;
  vn_antigo_consumo_id  rcf_consumos.consumo_id%TYPE;
  vn_novo_consumo_id    rcf_consumos.consumo_id%TYPE;
  vn_qtde               imp_declaracoes_lin.qtde%TYPE;

BEGIN
  IF (cmx_fnc_profile ('zzz') = 'S') OR (cmx_fnc_profile (yyy') = 'S' ) THEN
    SELECT tp_declaracao_id,
           dsi
    INTO   vn_tp_declaracao_id,
           você_dsi
    FROM   imp_declaracoes
    WHERE  declaracao_id = :old.declaracao_id;

    IF (cmx_pkg_tabelas.codigo (vn_tp_declaracao_id) IN ('16','17')) AND (você_dsi = 'N') THEN
      BEGIN
          OPEN cur_linha_decl(:old.declaracao_lin_id);
          FETCH cur_linha_decl
          INTO vn_qtde;
          CLOSE cur_linha_decl;

          SELECT antigo.consumo_id,
                 novo.consumo_id
          INTO   vn_antigo_consumo_id,
                 vn_novo_consumo_id
          FROM   rcf_consumos antigo,
                 rcf_consumos novo
          WHERE  antigo.nr_referencia        = :old.declaracao_id
          AND    novo.estoque_movimento_id   = antigo.estoque_movimento_id
          AND    novo.saida_movimento_id     = antigo.saida_movimento_id
          AND    novo.nr_referencia          IS NULL;

          UPDATE rcf_lancamentos
          SET consumo_id = vn_novo_consumo_id
          WHERE consumo_id = vn_antigo_consumo_id;

          DELETE FROM rcf_consumos
          WHERE consumo_id = vn_antigo_consumo_id;

          UPDATE rcf_consumos
          SET quantidade = quantidade+vn_qtde
          WHERE consumo_id = vn_novo_consumo_id;

       END;
     END IF;
   END IF;
COMMIT;   
END rcf_trg_exc_lin_decl;
Tirando as linhas que estão o PRAGMA e o COMMIT, é a view original, que dá erro quando o vn_tp_declaracao_id e o você_dsi = S.

Como nem todas as linhas passam por essa parte e menos ainda pelos profiles zzz e yyy, então a maioria das linhas são deletadas normalmente, mas, algumas ficam travadas por estarem utilizando esses profiles e acabam entrando no cursor.

Quando eu tento deletar estas linhas, me dá erro de dados não encontrados(ORA-01403: no data found), mas, a linha está lá na tabela.

Minhas dúvidas:

1) Está certo a forma de colocar o PRAGMA AUTONOMOUS_TRANSACTION?
2) Isso eu vou descobrir depois que colocar no lugar certo, mas, esse PRAGMA resolve o problema?

Obrigado pela ajuda,
Freidinger
schnu
Rank: Analista Pleno
Rank: Analista Pleno
Mensagens: 110
Registrado em: Ter, 24 Mai 2005 9:16 pm
Localização: Dongguan - Guangdong - China
Deus criou os loucos para confundir os sábios

O seu problema esta que você esta abrindo um curso na mesma tabela que você criou a trigger, por isso você PRECISA utilizar o Autonomous.

Desconheço outra maneira de abrir cursor na mesma tabela que esta a trigger sem usar o autonomous.

se alguém tem a solucao posta ai !!
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

1) Está certo a forma de colocar o PRAGMA AUTONOMOUS_TRANSACTION?
2) Isso eu vou descobrir depois que colocar no lugar certo, mas, esse PRAGMA resolve o problema?

O uso do PRAGMA AUTONOMOUS_T... cria uma nova sessão no oracle e executa o código dentro da nova sessão. É meio perigoso isso, então vou colocar uns links aqui pra você ver uns exemplos que o uso disso não funciona:
http://glufke.net/oracle/viewtopic.php?t=96
http://glufke.net/oracle/viewtopic.php?t=1537

Eu particularmente, só usso esse PRAGMA pra criar LOGS em outras tabelas e comitar, sem afetar a transação atual, ou seja, o log vai ser gravado mesmo se o programa original der ROLLBACK.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 16 visitantes