Problemas com Trigger

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
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

Bom dia Glufke,

Amigos...eu to aqui quebrando a cabeça e td +..hihi

O caso é o seguinte: Tenho uma trigger que ela entra em ação quando atualizo uma determinada tabela A com uma coluna A, onde esta coluna e um flag, com sim/não e nulo..td dentro de um forms!!

Exp do forms 6i:

col1 col2 col3 colA
999 xxxx 9999 sim - Se sim atualizo com 1 dando update em tab A col A
999 xxxx 9999 não - Se não atualizo com 0 dando update em tab A col A
999 xxxx 9999 ------Se null atualizo com 9 dando update em tab A col A

Daeee a trigger, busca as informações do q forem "sim", no caso, de valor 1 vira valor 7 na col A da tab A.

Agora vem o problema: quando clico no flag para sim, ele não consegue atualizar devido a trigger:

No forms mostra essa msg, quando aperto shift + f1
ORA-01403: no data found
ORA-06512: at "owner.tabA", line 50
ORA-04088: error during execution of trigger 'owner.tabA'

Já quando rodo o update no sqlplus8i ..aparece msg:

ERRO na linha 1:
ORA-01403: não há dados localizados

Segue a trigger:

Exp da trigger:

Selecionar tudo

CREATE OR REPLACE TRIGGER trg_a
       AFTER UPDATE ON tab_a
       FOR EACH ROW

begin

    if :new.colA = 1 then

       update tabA
        set colA = 7
       where colB = :old.colB;
      commit;

    end if;

end if;
Será q alguém já passou por isso?:roll:

Abs de seu amigo Hahu
Que Deus abençõe a todos!
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Brother,

Só uma questão:

Você está tentando dar um update numa coluna, caso o novo valor dela seja 01, você joga 07 nesta mesma coluna?

É este mesmo teu objetivo?

Outra coisa, atentar para o erro de Mutating ai.
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

Fala trevisolli,

então..assim..eu to lá no forms6i..daee eu mudo o flag para sim..oo sim corresponde ao 5 que é atualizado na tabA, nesta col A! A trigger só vai ler esse 5 e mudar para 7...entendeu?..só isso!! :roll:

erro de Mutating..vixi..nem sei o que é isso :oops:

Abs Hahu
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

Fala trevisolli,

então..assim..eu to lá no forms6i..daee eu mudo o flag para sim..oo sim corresponde ao 1 que é atualizado na tabA, nesta col A! A trigger só vai ler esse 1 e mudar para 7...entendeu?..só isso!! Rolling Eyes

erro de Mutating..vixi..nem sei o que é isso? Embarassed

ops: descupe e 1 para 7 e não 5 p/ 7..mauuu aí :oops:

Abs Hahu
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

Hahu,

Por acaso não existe uma outra trigger com o nome tabA sobre essa tabela?
Pois esse é o nome da trigger que deu o erro de NO_DATA_FOUND que você postou, e não a trg_a..

Caso você tenha trocado os nomes... a trigger trg_a tem apenas código que você postou? Pois não tem como nenhum dos comandos lá gerarem uma exceção de NO_DATA_FOUND...
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

...nossa...acho que ontem eu tava muito cansado ..porisso postei errado...bom, mas acredito que hj eu to um pouco melhor...hihi! :roll:
me desculpe amigos e que eu dormir só 4 hrs ontem..fiquei atrapalhado ao postar!! :oops:

então rogenaro, o nome da trigger é : trg_a e a tabela é tabA e que ná hora de postar eu quiz manter a privacidade da empresa em relação as tabela..dae eu troquei os nomes oficias por esse figurativos..me desculpe novamente! :roll:

Segue a correção:

Selecionar tudo

ORA-01403: no data found
 [b]ORA-06512: at "login_user.trg_a", line 50 [/b]
ORA-04088: error during execution of trigger 'login_user.trg_a' 
Hoje eu tava verificando, que quando mudo de :old para :new na condição if da col A, a trigger, deixa eu colocar no flag do forms6i a opção "não", daí ela atualiza normalmente!

De mudo a condição para um outro valor..por exemplo tipo "2", na condição do if que está na trigger..o forms deixa eu setar o flag como "sim", daí atualiza a tabA como 1 . É muito estranho, ora ela atualiza somente o "sim"..e ora somente atualiza o "não"!

Por que será que acontece isso ?:roll: ..alguém já passou por isso!

Abraços de seu amigo Hahu :wink:
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

Ué.. estranho que o código do erro dado seja o 01403..
Tentei replicar a situação aqui (pode ser que eu tenha entendido algo errado também):

Selecionar tudo

-- criar a tabela tabA
create table tabA
as
select 1 colA, 2 colB from dual
union all
select 3 colA, 4 colB from dual
union all
select 5 colA, 6 colB from dual;

-- criar a trigger trg_a
CREATE OR REPLACE TRIGGER trg_a
       AFTER UPDATE ON tabA
       FOR EACH ROW

begin

    if :new.colA = 1 then

       update tabA
        set colA = 7
       where colB = :old.colB;
      commit;

    end if;

end;

-- Realizar um update
update tabA
set    colA = 1
where  colB = 4;
O erro que foi gerado aqui (e que deveria ter acontecido para você também) foi o 04091 (Mutating table)

Selecionar tudo

ORA-04091: table USER.TABA is mutating, trigger/function may not see it
ORA-06512: at "USER.TRG_A", line 5
ORA-04088: error during execution of trigger 'USER.TRG_A'
pode ter sido um erro de digitação sua, mas a linha

Selecionar tudo

ORA-06512: at "login_user.trg_a", line 50[/cide] que você postou apresentou o erro na linha 50... por acaso não teria algo a mais no corpo da trigger?

Porque estou sem idéias no momento.. hehehe


Sei que o exemplo que você postou é mais simplificado em relação à sua trigger, mas seria possível alterar a trigger de AFTER UPDATE para BEFORE UPDATE?
[code]
CREATE OR REPLACE TRIGGER trg_a
       BEFORE UPDATE ON tabA
       FOR EACH ROW

begin

    if :new.colA = 1 then
      :new.colA := 7;
    end if;

end;
Quem sabe muda alguma coisa.. =P
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

Fala rogenaro,
Bom dia amigo..
você está coberto de razão é isso mesmo é 5 e não 50 de line..foi um zero a mais...foi realmente erro de digitação...esse erro de trigger mutante..tb acusou aqui..fiquei testando e percebi isso! Foi exatamente isso, igual ao que você postou!!
Ontem também mudei para before...mas não rolou!!

Dae pensei em criar uma package com duas triggers..a primeira trigger recebe da pkg uma tabelas do type, a segunda trigger e onde eu referencio essas tabelas dentro de um for!!

Mas ainda continuo na mesma..puts, estou que nem você sem idéias..já li a respeito das tabela mutantes..e de como contornar os erro..eee no livro de oracle 9i (programação pl/sql), menciona que agente tem que criar esse exemplo que citei da pkg e tb podemos colocar : referencing + o pragma transaction ! :roll:

Agradeço a você e a todos que estão me ajudando neste caso..pois está complicado!

Abs de seu amigo Hahu
Que Deus abençõe a todos!
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

Hj testei a trg_A e apresentou esse erro no forms6i...está lockando a tabA!!

Selecionar tudo

ORA-00060: deadlock detected while waiting for resource
ORA-06512: at "USER.TRG_A", line 5
ORA-04088: error during execution of trigger 'USER.TRG_A'
Não estou conseguindo contornar a situação!!

Tentei colocar no forms o "trigger on-lock", mas não surtiu efeito nenhum..apenas tirou esse erro citado acima..mas não atualiza o flag..buuuáa :cry: ..não sei mais o que faço...será que alguém tem alguma idéia?

Abs de seu amigo Hahu
Que Deus abençõe a todos!
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

Caramba Hahu!

Que coisa complicada!

Vamos lá:

- Como estava a trigger BEFORE INSERT que você citou primeiro? Ela fazia update na tabela tabA, ou você estava apenas alterado o valor do campo :new.colA, como eu fiz no meu exemplo? Pois se você precisar fazer um update, realmente será necessário usar o método de criar a package e 3 triggers (before update e after update a nivel de statement, e before insert a nivel de linha). Caso contrário, qual o erro apresentado?

- Como ficou a sua pacakge? foi algo parecido com isso? (Testei aqui e também funcionou sem problemas.. qual o erro que você encontrou?)

Selecionar tudo

create or replace package k_tabA as

  type tabA_rec is record
  ( rid rowid
  );

  type tabA_tbl is table of tabA_rec index by binary_integer;

  v_registros tabA_tbl;
  v_vazio     tabA_tbl;

end k_tabA;



create or replace trigger t_tabA_bu_stmt
before update on tabA
begin
  k_tabA.v_registros := k_tabA.v_registros; -- Esta trigger vai limpar a PL/SQL table a cada comando update.
end;


create or replace trigger t_tabA_bu_row
before update on tabA
for each row
begin
  -- Esta trigger irá armazenar os ROWIDS (ou a PK) do registro atualizado, para cada registro.
  k_tabA.v_registros(k_tabA.v_registros.count + 1).rid := :new.rowid;
end;

create or replace trigger t_tabA_au_stmt
after update on tabA
begin
  -- Esta trigger irá realizar os devidos processamentos, para cada registro armazenado anteriormente.
  for i in k_tabA.v_registros.first .. k_tabA.v_registros.last loop

    if k_tabA.v_registros.exists(i) then
      for x in
      (
        select * from tabA where rowid = k_tabA.v_registros(i).rid
      ) loop
        if x.colA = 1 then
          update tabA t
          set    t.colA  = 7
          where  t.rowid = k_tabA.v_registros(i).rid;
        end if;
      end loop;
    end if;

  end loop;
end;
- À primeira vista, acredito que o problema de deadlock provavelmente veio do PRAGMA AUTONOMOUS TRANSACTION. Este comando vai criar uma transação separada, que vai tentar atualizar a mesma tabela que já está sendo atualizada na sua seção...
Hahu
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 147
Registrado em: Qui, 16 Mar 2006 11:26 am
Localização: São Paulo
O mundo gira muito!!

Bom dia rogenaro!

Muito obrigado.. funcionou perfeitamente...to feliz pra caramba!!

Fica mais este exemplo, para os demais amigos que participam e contribuem para este forum!!:lol:

Abraços de seu amigo Hahu :wink:

Que Deus Abençõe a todos!
cicero.almeida
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 12
Registrado em: Seg, 05 Abr 2010 3:11 pm
Localização: BAHIA

Olá estou com um problema com essa trigger preciso de ajuda já tentei de tudo .

O que acontece é o seguinte existe uma tabela negociação_pacote onde eu preciso implementa uma trigger de after update, para atualizar 2 campos da linha que foi alterada na tabela. Um campo é referente a data de atualização e outro e o nome do usuario que esta logado no sistema .

Minha trigger esta assim

Selecionar tudo

CREATE OR REPLACE  TRIGGER tr_Negociacao_Pacote
AFTER UPDATE
ON TS.NEGOCIACAO_PACOTE 
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
 
 insert into ts.TEMP_NEGOCIACAO_PACOTE (v_localisa, cod_prestador_Ts, num_associado,dt_max) values (:old.cod_pacote,  :old.cod_prestador_ts, :new.val_negociado,sysdate );
  
 update  ts.NEGOCIACAO_PACOTE set dt_atu = sysdate, usuario_atu = ts_read_client_info where cod_prestador_Ts = (select  cod_prestador_Ts from ts.TEMP_NEGOCIACAO_PACOTE);
 
 truncate table TS.TEMP_NEGOCIACAO_PACOTE 
END tr_Negociacao_Pacote;
Criei uma tabela temporaria para grava valores da ultima linha alterada
mas tb n deu certo o erro foi o mesmo.

Selecionar tudo

ORA-04091: table TS.NEGOCIACAO_PACOTE is mutating, trigger/function may not see it
ORA-06512: at "TS.TR_NEGOCIACAO_PACOTE", line 7
ORA-04088: error during execution of trigger 'TS.TR_NEGOCIACAO_PACOTE'
Quem já se deparo com essa situação favor ajudar

grato cicero.
diegolenhardt
Moderador
Moderador
Mensagens: 1177
Registrado em: Qui, 15 Out 2009 10:28 am
Localização: Recife

Dentro de uma trigger você não pode referenciar a própria tabela da Trigger, ou seja, não pode fazer update, insert, delete, select, nada,

a tabela temporária funciona sim,
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

Além disso, Truncate é um comando DDL e não pode ser usado em PL/SQL, salvo utilização de DDL em SQL dinâmico, o que não é muito recomendado e o USER de sua aplicação provavelmente não terá privilégios para fazer.

Lembrando que triggers sempre rodam com os privilégios do usuário conectado, vulgo Invoker's Rights, ao contrário de procedures/functions que executam com os privilégios do owner do programa.

Para entender o motivo para não ser possível fazer selects, updates, etc em sua tabela na trigger dela própria (row level), leia o post abaixo com atenção, pode ser muito útil:
http://glufke.net/oracle/viewtopic.php?t=5801&start=25

Só uma observação, se você quiser modificar um atributo da própria linha que está sendo modificada, apenas atribua :new.set dt_atu = sysdate, por exemplo... e a mesma coisa nos demais campos.
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

Desculpa, postei informação incorreta, triggers sempre executam com definer's rights, ou seja, privilégios do owner. O que quer dizer que ele é provavelmente um usuário "super-privilegiado" e não deveria estar fazendo DDL em nome de outro usuário conectado.
cicero.almeida
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 12
Registrado em: Seg, 05 Abr 2010 3:11 pm
Localização: BAHIA

Obrigada pela ajuda!

Descobri logo a pós a postagem como altera a linha da tabela
mas valeu, mesmo minha trigger fico assim:

Selecionar tudo

CREATE OR REPLACE TRIGGER tr_Negociacao_Pacote_in
BEFORE insert
ON TS.NEGOCIACAO_PACOTE 
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN

 :new.dt_inclusao := SYSDATE;
 :new.usuario_inclusao := ts_read_client_info;
 
 
 
END tr_Negociacao_Pacote_in;
/
Atenciosamente
Cícero
Responder
  • Informação
  • Quem está online

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