ELSE
gren kan forenkles radikalt. Men et par ting mere er ineffektive / unøjagtige / farlige:
CREATE OR REPLACE FUNCTION sample_trigger_func()
RETURNS TRIGGER AS
$func$
BEGIN
IF TG_OP = 'DELETE' THEN
RAISE INFO 'OLD: %', OLD.name;
EXECUTE format('INSERT INTO %I SELECT ($1).*', TG_TABLE_NAME || '_deletes')
USING OLD #= hstore('{mod_op, mod_datetime}'::text[]
, ARRAY[left(TG_OP, 1), now()::text]);
RETURN OLD;
ELSE -- insert, update
NEW.mod_op := left(TG_OP, 1);
NEW.mod_datetime := now();
RETURN NEW;
END IF;
END
$func$ LANGUAGE plpgsql;
-
I
ELSE
gren bare tildele tilNY
direkte. Intet behov for mere dynamisk SQL - som ville udløse den samme trigger igen og forårsage en endeløs loop. Det er den primære fejl. -
RETURNER NY;
uden forIF
konstruktion ville bryde din triggerfunktion forDELETE
, daNY
er ikke tildelt til DELETEs. -
En nøglefunktion er brugen af
hstore
og hstore-operatøren#=
for dynamisk at ændre to valgte felter af den velkendte rækketype - det er ukendt på tidspunktet for skrivning af koden. På denne måde manipulerer du ikke med den originaleOLD
værdi, hvilket kan have overraskende bivirkning, hvis du har flere triggere ned i hændelseskæden.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);
Det ekstra modul
hstore
skal installeres. Detaljer:- Sådan indstilles værdien af det sammensatte variabelfelt ved hjælp af dynamisk SQL
- Videre kolonnenavne dynamisk for en postvariabel i PostgreSQL
Brug af
hstore(text[], text[])
variant her for at konstruere enhstore
værdi med flere felter på farten. -
Tildelingsoperatoren i plpgsql er
:=
: -
Bemærk, at jeg brugte kolonnenavnet
mod_datetime
i stedet for den vildledendemod_dato
, da kolonnen åbenbart er ettidsstempel
og ikke endato
.
Jeg tilføjede et par andre forbedringer, mens jeg var i gang. Og selve udløseren skulle se sådan ud:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();