Du kan använda format()
för att göra det mycket enklare att skapa en dynamisk SQL-fråga eftersom den automatiskt kommer att hantera identifierare och bokstaver på rätt sätt. En sak som folk vanligtvis förbiser är att du kan utöka ett enda postuttryck till alla dess kolumner med (...).*
- detta fungerar även för NEW
och OLD
registrera variabler i en trigger, t.ex. select (new).*
Du kan också skicka variabler till en dynamisk SQL med using
nyckelordet för execute
påstående. Det finns ingen anledning att konvertera posten fram och tillbaka mellan en post och en textrepresentation.
Genom att använda den möjligheten kan din triggerfunktion förenklas till:
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;
Använda platshållare som %I
och %L
gör det också möjligt att definiera själva SQL bara en gång och återanvända den. Dessa "parametrar" ersätts av format()
funktion (som bevarar $1
)
Observera användningen av ($1).*
inuti SQL-strängen. Det gör att execute
expandera postparametern $1
till alla dess kolumner. Själva posten skickas "native" med USING
nyckelord.
Användningen av INSERT
utan en målkolumnlista (insert into some_table ...
istället för insert into some_table (col1, col2, ...) ...
) är en ganska bräcklig sak att göra. Om källan och målet inte matchar kan infogningen misslyckas ganska lätt. .
Om du inte kör omfattande rapportering på granskningstabellerna (där att ha explicita kolumnnamn skulle vara mycket effektivare) kanske du vill tänka på en mer generisk granskningsutlösare med en JSON
eller HSTORE
kolumn för att lagra hela posten. Det finns flera färdiga granskningsutlösare tillgängliga:
- 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