Você pode usar
format()
para tornar a criação de uma consulta SQL dinâmica muito mais fácil, pois ela lidará automaticamente com identificadores e literais corretamente. Uma coisa que as pessoas geralmente ignoram é que você pode expandir uma única expressão de registro para todas as suas colunas usando (...).*
- isso também funciona para NEW
e OLD
gravar variáveis em um gatilho, por exemplo select (new).*
Você também pode passar variáveis para um SQL dinâmico com o
using
palavra-chave do execute
declaração. Não há necessidade de converter o registro entre um registro e uma representação de texto. Usando essa possibilidade, sua função de gatilho pode ser simplificada para:
DECLARE
l_sql text;
BEGIN
IF TG_TABLE_SCHEMA = 'public' THEN
newtable := TG_TABLE_NAME || '_actividad';
ELSE
newtable := TG_TABLE_SCHEMA || '_' || TG_TABLE_NAME || '_actividad';
END IF;
PERFORM creartablaactividad(TG_TABLE_SCHEMA, TG_TABLE_NAME);
l_sql := 'INSERT INTO actividad.%I SELECT current_user, current_timestamp, %L, ($1).*';
IF TG_OP = 'DELETE' THEN
execute format(l_sql, newtable, 'D') using OLD;
RETURN OLD;
ELSE
-- covers UPDATE and INSERT
execute format(l_sql, newtable, 'U') using NEW;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
Usando espaços reservados como
%I
e %L
também torna possível definir o SQL real apenas uma vez e reutilizá-lo. Esses "parâmetros" são substituídos pelo format()
função (que preserva o $1
) Observe o uso de
($1).*
dentro da string SQL. Isso fará com que o execute
expanda o parâmetro de registro $1
a todas as suas colunas. O próprio registro é passado "nativamente" com o USING
palavra-chave. O uso de
INSERT
sem uma lista de colunas de destino (insert into some_table ...
em vez de insert into some_table (col1, col2, ...) ...
) é uma coisa muito frágil de se fazer. Se a origem e o destino não corresponderem, a inserção pode falhar facilmente. . Se você não executar relatórios massivos nas tabelas de auditoria (onde ter nomes de colunas explícitos seria muito mais eficiente), convém pensar em um gatilho de auditoria mais genérico usando um
JSON
ou HSTORE
coluna para armazenar todo o registro. Existem vários gatilhos de auditoria prontos disponíveis:- http://okbob.blogspot. de/2015/01/most-simply-implementation-of-history.html
- https://github.com/wingspan/wingspan-auditing
- https://www.cybertec-postgresql.com /en/tracking-changes-in-postgresql/
- https://wiki.postgresql.org/wiki/Audit_trigger_91plus