Fórum Trigger para pegar somente o que foi modificado no registro #429939

28/11/2012

0

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.
Paulo Pinto

Paulo Pinto

Responder

Posts

28/11/2012

Paulo Pinto

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;


Responder

Gostei + 0

28/11/2012

Jair N.

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.


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;


Responder

Gostei + 0

28/11/2012

Paulo Pinto

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?


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;

Responder

Gostei + 0

31/07/2013

José

Obrigado Paulo pelo retorno e por demonstrar como conseguiu fazer, sendo assim estou dando o tópico por concluído.
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar