- Este tópico contém 6 respostas, 5 vozes e foi atualizado pela última vez 17 anos, 9 meses atrás por
Marcio68Almeida.
-
AutorPosts
-
25 de maio de 2008 às 5:58 am #81857
drhoffman
ParticipanteBoas pessoal , Tou de volta de um projecto para a faculdade e tou aqui com uma duvida! é o seguinte! Uma factura pode ter associados diversos pagamentos! eu quando estou a introduzir um pagamento quero que ele me actualize o total na factura! eu pela minha logica devia fazer um after insert mas quando o faço obtenho este erro quando insiro um pagamento
“One error saving changes to table “SYSDBA”.”PAGAMENTOS”:
Row 6: ORA-04091: table SYSDBA.PAGAMENTOS is mutating, trigger/function may not see it
ORA-06512: at “SYSDBA.PAGAMENTOS_T1″, line 5
ORA-04088: error during execution of trigger ‘SYSDBA.PAGAMENTOS_T1’
ORA-06512: at line 1”Pondo o before ele funciona mas ele vai fazer a soma de todos os pagamentos anteriores referente á factura mas nao soma o ultimo valor do pagamento , ou seja , o do pagamento que esta a ser inserido quando o trigger é despolotado! eu acho que com um after resolvia o problema
quando insiro um pagamento ele da me o erro descrito acima e nao sei o que fazer mais!O Trigger é o seguinte:
create or replace
trigger “PAGAMENTOS_T1”
before
insert on “PAGAMENTOS”
for each row
begin
DECLARE
v_valor number;
BEGIN
SELECT nvl(sum(valor),0)
INTO v_valor
FROM PAGAMENTOS
WHERE id_factura = :new.id_factura;
UPDATE facturas
SET valor_factura = v_valor;
END;
END;Alguem me consegue dar uma ajudinha?
Obrigado 🙂
25 de maio de 2008 às 6:05 am #81858drhoffman
ParticipanteOutro problema que tenho é que o trigger actualiza-me todas as facturas e nao apenas a factura em que o pagamento esta a ser inserido! deve ter a ver com esta linha
WHERE id_factura = :new.id_factura;
o meu raciocionio foi , que ele me selecionasse a factura que foi introduzida no pagamento!
26 de maio de 2008 às 4:55 pm #81864DanielB
Participantepq nao escrive o trigger assim
create or replace
trigger “PAGAMENTOS_T1”
before
insert on “PAGAMENTOS”
for each row
BEGIN
UPDATE facturas
SET valor_factura = nvl(:new.valor,0) + nvl(valor_factura,0)
WHERE id_factura = :new.id_factura;
END;26 de maio de 2008 às 5:56 pm #81866Leonardo Litz
ParticipanteOla… o erro de trigger mutante ocorre pois vc esta tentando efetuar uma operacao em uma tabela que esta sendo alterada no momento, neste caso o oracle interfere dizendo que nao ha garantia de que o dado retornado pode nao esta correto, no post anterior ja resolvera seu problema. Oque vc tb pode fazer eh colocar um pragma na trigger para que o oracle nao considere esta situacao.
Coloque esta linha apos o begin da trigger
Pragma Autonomous_Transaction;
26 de maio de 2008 às 10:59 pm #81872andrezavan
ParticipanteOlá… também estou com o mesmo problema. No meu caso eu tenho uma trigger que chama uma procedure quando essa trigger é disparada, a processedure realizar a operacao na mesma tabela que esta o evento da trigger. Tentei colocar o Pragma Autonomous_Transaction porém o Developer diz que nao possivel especifiar o pragma.
Desde já agradeço.
André Zavan
[quote=”Litz”:y99gzmlz]Ola… o erro de trigger mutante ocorre pois vc esta tentando efetuar uma operacao em uma tabela que esta sendo alterada no momento, neste caso o oracle interfere dizendo que nao ha garantia de que o dado retornado pode nao esta correto, no post anterior ja resolvera seu problema. Oque vc tb pode fazer eh colocar um pragma na trigger para que o oracle nao considere esta situacao.
Coloque esta linha apos o begin da trigger
Pragma Autonomous_Transaction;[/quote]
27 de maio de 2008 às 3:24 am #81873drhoffman
Participanteboas pessoal! consegui resolver o problema como voces me disseram mas surgiu me outro! eu nem com o pragma consigo que ele me deixe fazer o after insert! agora tenho este erro
“One error saving changes to table “SYSDBA”.”PAGAMENTOS”:
Row 5: ORA-06519: active autonomous transaction detected and rolled back
ORA-06512: at “SYSDBA.TRG_ACTUALIZA_FACTURA”, line 11
ORA-04088: error during execution of trigger ‘SYSDBA.TRG_ACTUALIZA_FACTURA’
ORA-06512: at line 1″mas de qualquer maneira o trigger ta a funciona e fica aqui , mas tenho outro problema. eu criei outro tigger que dependendo do tipo de quota do socio ele atribui um valor no pagamento
o trigger e este
create or replace TRIGGER TRG_ATRIBUI_VALOR
BEFORE INSERT ON PAGAMENTOS
FOR EACH ROW
DECLARE
v_valor PAGAMENTOS.valor%TYPE;
v_tipo_socio tipos_socio.id_tipo_socio% TYPE;
BEGIN
SELECT distinct tq.valor_quota
into v_valor_quota
from tipos_quota tq,socios s
where s.id_tipo_quota=tq.id_tipo_quota
and s.id_pessoa=:new.id_pessoa;
:NEW.valor := v_valor_quota;
END;o trigger ta a funcionar mas se tiver os dois triggers a funcionar ao mesmo tempo ele introduz me o pagamento de acordo com o que eu quero mas nao me incrementa o valor na factura! eu acho que o problema é por serem ambos before insert mas o problema é que mesmo com o pragma nao consigo resolver esta situacao! alguem tem sugestoes? o que eu quero e que quando introduzo um pagamento ele automaticamente introduz o pagamento e depois acumula na factura! se eu puser apenas um deles a trabalhar no sistema eles funcionam sem problemas mas quando estão os dois ele so me introduz o pagamento e nao me actualiza a factura! obrigado.
Aqui fica o script
create or replace
trigger “TRG_ACTUALIZA_FACTURA”
before
insert on “PAGAMENTOS”
for each row
DECLARE
v_valor number;
BEGIN
SELECT SUM(valor)
INTO v_valor
FROM PAGAMENTOS;
UPDATE facturas
SET valor_factura = :NEW.Valor + v_valor
WHERE id_factura = :NEW.id_factura;
END;27 de maio de 2008 às 5:02 pm #81883Marcio68Almeida
ParticipanteTrigger é uma ferramenta maravilhosa, mas creio que você está entrando em um terreno perigoso, pois estou percebendo que muito em breve você terá triggers encadeadas, isso costuma gerar um travamento no sistema e é muito difícil de encontrar o erro quando isso acontece, pois não é fácil identificar em que ponto do processo travou…
Talvez seja mais interessante fazer as atualizações em processos batch e views informando on-line os valores atualizados.
Aproveite para verificar se nesses seus testes você não deixou processos pendentes :
Select s.sid, s.serial#, o.owner, s.lockwait, s.username, s.osuser, s.terminal, s.status, l.id2, decode (NVL (l.id2, 0), 0, o.object_name, 'Trans-' || to_char (l.id1)) object_name, decode (NVL (l.type, '.'), 'BL', 'Buffer hash table instance', 'CF', 'Control file schema global enqueue', 'CU', 'Cursor bind', 'CI', 'Cross-instance function invocation instance','DF', 'Data file instance', 'JQ', 'Job queue', 'DL', 'Direct loader parallel index create', 'TX', 'Transaction enqueue', 'UL', 'User supplied', 'DM', 'Mount/startup db primary/secondary instance', 'DR', 'Distributed recovery process', 'DX', 'Distributed transaction entry', 'TM', 'DML enqueue', l.type) type, decode (NVL (l.lmode, 0), 0, '--Waiting--', 1, 'Null', 2, 'Row Share', 3, 'Row Excl', 4, 'Share', 5, 'Sha Row Exc', 6, 'Exclusive', 'Other') "Lock Mode", decode (NVL (l.request, 0), 0, ' - ', 1, 'Null', 2, 'Row Share', 3, 'Row Excl', 4, 'Share', 5, 'Sha Row Exc', 6, 'Exclusive', 'Other') "Req Mode"
From gv$lock l, gv$session s, dba_objects o
Where s.sid = l.sid (+)
and l.id1 = o.object_id (+)
and s.username is not null
Order by l.id2, s.sid -
AutorPosts
- Você deve fazer login para responder a este tópico.