Trigger para pegar somente o que foi modificado no registro
Pessoal na documentação do postgres tem esse exemplo
[url]http://www.postgresql.org/docs/9.0/static/plpgsql-trigger.html#PLPGSQL-TRIGGER-AUDIT-EXAMPLE[/url]
Como posso fazer pra pegar somente o que foi modificado? utilizando esse exemplo.
[url]http://www.postgresql.org/docs/9.0/static/plpgsql-trigger.html#PLPGSQL-TRIGGER-AUDIT-EXAMPLE[/url]
Como posso fazer pra pegar somente o que foi modificado? utilizando esse exemplo.
Paulo Pinto
Curtidas 0
Respostas
Paulo Pinto
28/11/2012
Parecido com isso, mas somente o que for modificado no update.
CREATE OR REPLACE FUNCTION process_emp_audit()
RETURNS trigger AS
$BODY$
BEGIN
--
-- Create a row in emp_audit to reflect the operation performed on emp,
-- make use of the special variable TG_OP to work out the operation.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO logs SELECT now(), TG_OP, TG_TABLE_NAME, cast('Registro Antigo '||OLD.* as text) ;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
--> AQUI PEGAR SOMENTE O QUE FOI MODIFICADO...
--> OU COM UM FOR, SABER O NOME DA COLUNA PRA FICA LADO A LADO
--> Exemplo:
--> Coluna Modificada | Registro Antigo | Registro Novo
--> pess_nome | Paulo | Paulo Alexandre
INSERT INTO logs SELECT now(), TG_OP, TG_TABLE_NAME, cast('Registro Antigo '||OLD.* ||' Novo Registro '||OLD.* as text) ;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
-- INSERT INTO logs SELECT null, null, TG_OP, TG_TABLE_NAME, 0, 0, cast(NEW.* as text) ;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
GOSTEI 0
Jair N.
28/11/2012
Bom Dia, seguinte lembre-se que o OLD e o NEW é um array dos seus campos, você pode comparar num processo o que foi alterado o que estava antes e depois eu prefiro guardar tudo passando para o campo texto Exemplo:
Antes: ARRAY_TO_STRING(ARRAY[OLD], '|')
para pegar campo a campo use a exemplo o sequencial dos campos e o nome Exemplo:
SELECT pg_attribute.attnum
, pg_attribute.attname
FROM pg_attribute
INNER JOIN pg_type
ON (pg_type.typrelid = pg_attribute.attrelid)
WHERE (pg_type.typname = "TG_RELNAME") -- nome da tabela para pesquisa
AND (pg_attribute.attstattarget = -1)
Bem, eu não descobri outra maneira de validar o que foi mudado sem fazer um processo de comparação entre o antes e o agora... Outra veja a necessidade de guardar os nomes dos campos, pois a tabela pode mudar conforme novas implementações.
Atc.
Antes: ARRAY_TO_STRING(ARRAY[OLD], '|')
para pegar campo a campo use a exemplo o sequencial dos campos e o nome Exemplo:
SELECT pg_attribute.attnum
, pg_attribute.attname
FROM pg_attribute
INNER JOIN pg_type
ON (pg_type.typrelid = pg_attribute.attrelid)
WHERE (pg_type.typname = "TG_RELNAME") -- nome da tabela para pesquisa
AND (pg_attribute.attstattarget = -1)
Bem, eu não descobri outra maneira de validar o que foi mudado sem fazer um processo de comparação entre o antes e o agora... Outra veja a necessidade de guardar os nomes dos campos, pois a tabela pode mudar conforme novas implementações.
Atc.
Parecido com isso, mas somente o que for modificado no update.
CREATE OR REPLACE FUNCTION process_emp_audit()
RETURNS trigger AS
$BODY$
BEGIN
--
-- Create a row in emp_audit to reflect the operation performed on emp,
-- make use of the special variable TG_OP to work out the operation.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO logs SELECT now(), TG_OP, TG_TABLE_NAME, cast('Registro Antigo '||OLD.* as text) ;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
--> AQUI PEGAR SOMENTE O QUE FOI MODIFICADO...
--> OU COM UM FOR, SABER O NOME DA COLUNA PRA FICA LADO A LADO
--> Exemplo:
--> Coluna Modificada | Registro Antigo | Registro Novo
--> pess_nome | Paulo | Paulo Alexandre
INSERT INTO logs SELECT now(), TG_OP, TG_TABLE_NAME, cast('Registro Antigo '||OLD.* ||' Novo Registro '||OLD.* as text) ;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
-- INSERT INTO logs SELECT null, null, TG_OP, TG_TABLE_NAME, 0, 0, cast(NEW.* as text) ;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
GOSTEI 0
Paulo Pinto
28/11/2012
Boa tarde Jair, consegui fazer, ficou simples e eficaz...
mas minha conversão do registro para ARRAY tem uma "Adaptação técnica" rsrs
tem outro jeito de converter isso?
mas minha conversão do registro para ARRAY tem uma "Adaptação técnica" rsrs
tem outro jeito de converter isso?
CREATE OR REPLACE FUNCTION process_emp_audit()
RETURNS trigger AS
$BODY$
DECLARE
rec RECORD;
textolog text;
Antes varchar array;
Depois varchar array;
nomecampo varchar;
nomescampos varchar array;
i integer;
texto text;
BEGIN
textolog = '';
i = 0;
--
-- Create a row in emp_audit to reflect the operation performed on emp,
-- make use of the special variable TG_OP to work out the operation.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO logs SELECT 0, now(), TG_OP, TG_TABLE_NAME, 0, 0, cast('Registro Antigo '||OLD.* as text) ;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
--> AQUI PEGAR SOMENTE O QUE FOI MODIFICADO...
--> OU COM UM FOR, SABER O NOME DA COLUNA PRA FICA LADO A LADO
--> Exemplo:
--> Coluna Modificada | Registro Antigo | Registro Novo
--> pess_nome | Paulo | Paulo Alexandre
textolog = 'Coluna Modificada | Registro Antigo | Registro Novo\n';
---------------------ADAPTAÇÃO TÉCNICA -------------------------------
texto = cast(OLD as text);
texto = substr(texto,2 ,length(texto)-2);
Antes = string_to_array(texto,',');
texto = cast(NEW as text);
texto = substr(texto,2 ,length(texto)-2);
Depois = string_to_array(texto,',');
----------------------------------------------------------------------
nomescampos = ARRAY(select attname FROM pg_attribute WHERE attrelid = TG_RELID AND attstattarget = -1 order by attnum);
for i in 1..array_length(nomescampos, 1)
LOOP
IF Antes[i] <> Depois[i] THEN
textolog = textolog||nomescampos[i]||'|'||Antes[i]||'|'||Depois[i]||'\n';
END IF;
END LOOP;
INSERT INTO logs SELECT 0, now(), TG_OP, TG_TABLE_NAME, 0, 0, textolog ;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
-- INSERT INTO logs SELECT null, null, TG_OP, TG_TABLE_NAME, 0, 0, cast(NEW.* as text) ;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
GOSTEI 0
José
28/11/2012
Obrigado Paulo pelo retorno e por demonstrar como conseguiu fazer, sendo assim estou dando o tópico por concluído.
GOSTEI 0