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
ELSEgren bare tildele tilNYdirekte. 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 forIFkonstruktion ville bryde din triggerfunktion forDELETE, daNYer ikke tildelt til DELETEs. -
En nøglefunktion er brugen af
hstoreog 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 originaleOLDvæ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
hstoreskal 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 enhstoreværdi med flere felter på farten. -
Tildelingsoperatoren i plpgsql er
:=: -
Bemærk, at jeg brugte kolonnenavnet
mod_datetimei stedet for den vildledendemod_dato, da kolonnen åbenbart er ettidsstempelog 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();