Puoi usare format()
per rendere la creazione di una query SQL dinamica molto più semplice in quanto gestirà automaticamente gli identificatori e i valori letterali correttamente. Una cosa che di solito le persone trascurano è che puoi espandere una singola espressione di record a tutte le sue colonne usando (...).*
- funziona anche per NEW
e OLD
registrare le variabili in un trigger, ad es. select (new).*
Puoi anche passare variabili a un SQL dinamico con using
parola chiave del execute
dichiarazione. Non è necessario convertire il record avanti e indietro tra un record e una rappresentazione testuale.
Usando questa possibilità, la tua funzione di attivazione può essere semplificata in:
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;
Utilizzo di segnaposto come %I
e %L
consente inoltre di definire l'SQL effettivo una sola volta e di riutilizzarlo. Questi "parametri" sono sostituiti da format()
funzione (che conserva il $1
)
Nota l'uso di ($1).*
all'interno della stringa SQL. Ciò farà execute
istruzione espandi il parametro del record $1
a tutte le sue colonne. Il record stesso viene passato "nativamente" con il USING
parola chiave.
L'uso di INSERT
senza un elenco di colonne di destinazione (insert into some_table ...
invece di insert into some_table (col1, col2, ...) ...
) è una cosa piuttosto fragile da fare. Se l'origine e la destinazione non corrispondono, l'inserimento può fallire abbastanza facilmente. .
Se non esegui report di massa sulle tabelle di controllo (dove avere nomi di colonna espliciti sarebbe molto più efficiente), potresti pensare a un trigger di controllo più generico utilizzando un JSON
o HSTORE
colonna per memorizzare l'intero record. Sono disponibili diversi trigger di audit già pronti:
- http://okbob.blogspot. de/2015/01/most-simply-implementation-of-history.html
- https://github.com/wingspan/wingspan-auditing
- https://www.cybertec-postgresql.com /it/monitorare-i-cambiamenti-in-postgresql/
- https://wiki.postgresql.org/wiki/Audit_trigger_91plus