Suponha que eu tenha a seguinte tabela:
CREATE TABLE data (
key TEXT primary key,
some_interesting_value TEXT,
inserted TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
last_seen TIMESTAMP WITH TIME ZONE
);
Então eu posso criar um gatilho para definir a coluna "atualizada" assim:
CREATE TRIGGER set_updated_col
AFTER UPDATE ON data
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE set_updated_timestamp();
A last_seen
coluna neste caso contém um timestamp que é atualizado toda vez que um processo é executado (com algumas condições). No entanto, esse valor não é interessante para acompanhar as atualizações da tabela. No meu caso, tenho muitas dessas tabelas. Todos eles contêm informações sobre dispositivos físicos de rede, e o valor "last_seen" é importante para cada entidade.
O acionador acima definirá o carimbo de data/hora "atualizado", mesmo que apenas o valor "last_seen" seja modificado.
No meu caso eu quero evitar isso.
Eu poderia nomear manualmente todas as colunas da WHEN
cláusula, mas então, se eu adicionar uma coluna à tabela, existe o risco de ela ser esquecida na trigger.
Existe uma maneira de "remover" a last_seen
coluna de OLD.*
?
Como exemplo de código:
-- This should NOT trigger a change to `updated`
UPDATE data SET last_seen=NOW() WHERE key='foobar';
-- this SHOULD trigger a change to `updated`
UPDATE data SET some_interesting_value='foo', last_seen=NOW() WHERE key='foobar'
Não tenho certeza sobre o impacto no desempenho, mas você pode converter linha em jasonb, remover campo e comparar objetos json.
Então, mudar
WHEN (OLD.* IS DISTINCT FROM NEW.*)
parawhen (row_to_json(old)::jsonb - 'last_seen' is distinct from row_to_json(new)::jsonb - 'last_seen')
fará o trabalho.Além disso, se você quiser modificar
NEW.updated
, deve serBEFORE UPDATE
trigger, nãoAFTER UPDATE
.