- Este tópico contém 6 respostas, 5 vozes e foi atualizado pela última vez 17 anos, 2 meses atrás por
jspaulonci.
-
AutorPosts
-
30 de dezembro de 2008 às 10:20 pm #84495
felipeldm
ParticipantePrezados,
Primeiramente desculpe se alguém já tiver postado algo nesse sentido. O ambiente em que me deparo é o seguinte:
1) Existem algumas tabelas no meu banco que necessito auditar, contudo, algumas dessas tabelas possuem mais de 30 colunas.
2) A trigger que eu quero é BEFORE UPDATE, pra gravar meu registro antes de o mesmo ser atualizado. Eu poderia fazer uma tranquilamente gravando todos os registros antigos e todos os novos, porém ficaria difícil auditar já que tem algumas tabelas com muitas colunas.
O que eu queria era:
Que no nomento em que a trigger for disparada ela detectasse apenas a(s) coluna(s) que foram modificadas e não precisasse gravar o registro todo na tabela de auditoria.Dessa forma a tabela teria a estrutura:
* COD_EVENTO – Codigo do evento;
* Data – Contendo SYSDATE;
* Tabela – Tabela que sofreu alteração.
* Usuario – Usuario que alterou a tabela (SYS_CONTEXT);
* ALTERACAO – Algo do tipo “O VALOR DA COLUNA TAL MUDOU DISSO PARA ISSO”.Assim ficaria perfeito, eu poderia integrar várias triggers gravando nessa mesma tabela.
Aguardo e desde já agradeço a todos!!!
Felipe Lima
31 de dezembro de 2008 às 12:14 am #84496Rodrigo Mesquita
Participanteutilize as variáveis :NEW e :OLD
exemplo para a coluna código
IF :NEW.CODIGO :OLD.CODIGO THEN
— coloque o insert na tabela de auditoria
End IF;
coloque isso para todos os campos que possam ser atualizados
31 de dezembro de 2008 às 12:20 am #84498felipeldm
ParticipanteEu já até pensei nisso…..
Mas será que é a única maneira???Já pensou eu fazendo isso pra uma tabela que tem mais de 50 colunas???
50 IFs com insert dentro…. complicado neh???Acho que pode existir uma maneira mais fácil.
Mas se não houver essa vai adiantar sim.Obrigado de toda forma…
Felipe Lima
2 de janeiro de 2009 às 5:18 am #84505Leonardo Litz
ParticipanteFelipe…
cara faca um gerador que leia o metadados e gere os ifs automaticamente, assim vc não precisa digitar if a if…
Fora isso voce tb pode fazer trigger por coluna, nesta forma voce devera gerar um trigger para cada coluna… as ai irá gerar uma demanda maior e a performace irá diminuir…
Vlw Leonardo Litz
7 de janeiro de 2009 às 4:59 pm #84557felipeldm
ParticipanteOlá mais uma vez pessoal…
Como não surgiu uma solução mais “compacta” hehehe tive que fazer da seguinte maneira, segue um exemplo que audita uma tabelinha do sistema:
CREATE OR REPLACE TRIGGER TR_AUDITA_ITEM_VDP BEFORE UPDATE ON ITEM_VDP
FOR EACH ROWDECLARE
VCOD_EVENTO TB_AUDITA_ITENS.COD_EVENTO%TYPE;
VOS_USER TB_AUDITA_ITENS.USUARIO%TYPE;
VVLR_TXT TB_AUDITA_ITENS.VLR_ALTERADO%TYPE;BEGIN
SELECT SYS_CONTEXT(‘USERENV’,’OS_USER’) INTO VOS_USER FROM DUAL;SELECT MAX(COD_EVENTO) INTO VCOD_EVENTO
FROM TB_AUDITA_ITENS
WHERE COD_ITEM = :OLD.COD_ITEM;IF VCOD_EVENTO IS NULL THEN
VCOD_EVENTO := 0;
END IF;IF :OLD.COD_EMPRESA :NEW.COD_EMPRESA THEN
VVLR_TXT := ‘A COLUNA COD_EMPRESA MUDOU DE ‘||:OLD.COD_EMPRESA||’ PARA ‘||:NEW.COD_EMPRESA;
GOTO INSERE;ELSIF :OLD.COD_ITEM :NEW.COD_ITEM THEN
VVLR_TXT := ‘A COLUNA COD_ITEM MUDOU DE ‘||:OLD.COD_ITEM||’ PARA ‘||:NEW.COD_ITEM;
GOTO INSERE;ELSIF :OLD.PRE_UNIT_BRUT :NEW.PRE_UNIT_BRUT THEN
VVLR_TXT := ‘A COLUNA PRE_UNIT_BRUT MUDOU DE ‘||:OLD.PRE_UNIT_BRUT||’ PARA ‘||:NEW.PRE_UNIT_BRUT;
GOTO INSERE;ELSIF :OLD.COD_GRUPO_ITEM :NEW.COD_GRUPO_ITEM THEN
VVLR_TXT := ‘A COLUNA COD_GRUPO_ITEM MUDOU DE ‘||:OLD.COD_GRUPO_ITEM||’ PARA ‘||:NEW.COD_GRUPO_ITEM;
GOTO INSERE;ELSIF :OLD.IES_LISTA_PRECO :NEW.IES_LISTA_PRECO THEN
VVLR_TXT := ‘A COLUNA IES_LISTA_PRECO MUDOU DE ‘||:OLD.IES_LISTA_PRECO||’ PARA ‘||:NEW.IES_LISTA_PRECO;
GOTO INSERE;ELSIF :OLD.PRE_UNIT_BRUT_EXP :NEW.PRE_UNIT_BRUT_EXP THEN
VVLR_TXT := ‘A COLUNA PRE_UNIT_BRUT_EXP MUDOU DE ‘||:OLD.PRE_UNIT_BRUT_EXP||’ PARA ‘||:NEW.PRE_UNIT_BRUT_EXP;
GOTO INSERE;ELSIF :OLD.COD_TIP_CARTEIRA :NEW.COD_TIP_CARTEIRA THEN
VVLR_TXT := ‘A COLUNA COD_TIP_CARTEIRA MUDOU DE ‘||:OLD.COD_TIP_CARTEIRA||’ PARA ‘||:NEW.COD_TIP_CARTEIRA;
GOTO INSERE;END IF;
<>
INSERT INTO TB_AUDITA_ITENS(COD_EVENTO,
DATA_ATUA,
HORA_ATUA,
USUARIO,
TABELA,
COD_EMPRESA,
COD_ITEM,
VLR_ALTERADO)
VALUES(VCOD_EVENTO+1,
TO_CHAR(SYSDATE,’DD/MM/YY’),
TO_CHAR(SYSDATE,’HH24:MM:SS’),
VOS_USER,
‘ITEM_VDP’,
:OLD.COD_EMPRESA,
:OLD.COD_ITEM,
VVLR_TXT);END;
Funcionar funciona sim, só é ruim para as tabelas imensas que tem no banco…
Valeu galera!!!
7 de janeiro de 2009 às 5:54 pm #84561Marcio68Almeida
ParticipanteExiste uma sollução um pouco mais simples (ou complexa, não sei como você vai encarar)… risos…
Crie uma função que fará o insert, passe o nome da tabela e dois vetores como parâmetro.
O primeiro array vai possuir os dados novos e o segundo os dados antigos.
Faça um loop que leia o vetor pelo seu tamanho e insira só os que for diferente…
Só não me peça para fazer a função por que sou preguiçoso… 😳
Não lembro se há alguma restrição passar array como parâmetro… 💡7 de janeiro de 2009 às 8:27 pm #84565jspaulonci
ParticipantePessoal é Oracle 10g ?, (pois no 9i tem algumas limitações) , dá uma pesquisada pois no 10 tem muitos recursos de auditoria, auditar esta tabela de 30 colunas através de trigger será meio pesado para o Banco, (é claro que irá dependender do número de inserts ,updates e deletes) mas se fosse eu , partiria para os recursos disponíves em nível de banco ou até dar uma pesquisada no Oracle Vault.
Não devo ter ajudado muito.
Spaulonci
-
AutorPosts
- Você deve fazer login para responder a este tópico.