U kunt format()
. gebruiken om het maken van een dynamische SQL-query veel gemakkelijker te maken, omdat het automatisch correct omgaat met identifiers en letterlijke waarden. Een ding dat mensen meestal over het hoofd zien, is dat u een enkele recorduitdrukking kunt uitbreiden naar alle kolommen met behulp van (...).*
- dit werkt ook voor NEW
en OLD
registreer variabelen in een trigger, b.v. select (new).*
U kunt ook variabelen doorgeven aan een dynamische SQL met de using
trefwoord van de execute
uitspraak. Het is niet nodig om het record heen en weer te converteren tussen een record en een tekstweergave.
Met behulp van die mogelijkheid kan uw triggerfunctie worden vereenvoudigd tot:
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;
Plaatsaanduidingen gebruiken zoals %I
en %L
maakt het ook mogelijk om de eigenlijke SQL slechts één keer te definiëren en opnieuw te gebruiken. Die "parameters" worden vervangen door het format()
functie (die de $1
. behoudt )
Let op het gebruik van ($1).*
binnen de SQL-string. Dat maakt de execute
statement breid de recordparameter uit $1
naar al zijn kolommen. Het record zelf wordt "native" doorgegeven met de USING
zoekwoord.
Het gebruik van INSERT
zonder een doelkolomlijst (insert into some_table ...
in plaats van insert into some_table (col1, col2, ...) ...
) is een vrij kwetsbaar iets om te doen. Als de bron en het doel niet overeenkomen, kan de invoeging vrij gemakkelijk mislukken. .
Als u geen massale rapportage uitvoert op de controletabellen (waar het hebben van expliciete kolomnamen veel efficiënter zou zijn), wilt u misschien een meer generieke controletrigger bedenken met behulp van een JSON
of HSTORE
kolom om het hele record op te slaan. Er zijn verschillende kant-en-klare audittriggers beschikbaar:
- 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