INNE
gałąź można radykalnie uprościć. Ale kilka innych rzeczy jest nieefektywnych / niedokładnych / niebezpiecznych:
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;
-
W
INNY
gałąź po prostu przypisz doNOWY
bezpośrednio. Nie ma potrzeby stosowania bardziej dynamicznego kodu SQL — który ponownie uruchomiłby ten sam wyzwalacz, powodując niekończącą się pętlę. To jest główny błąd. -
POWRÓT NOWOŚĆ;
pozaJEŻELI
konstrukcja zepsuje funkcję wyzwalacza dlaDELETE
, ponieważNOWOŚĆ
nie jest przypisany do DELETE. -
Kluczową funkcją jest użycie
hstore
i operator hstore#=
aby dynamicznie zmieniać dwa wybrane pola dobrze znanego typu wiersza - to jest nieznane w momencie pisania kodu. W ten sposób nie manipulujesz przy oryginalnymSTARYM
wartość, która może mieć zaskakujący efekt uboczny, jeśli masz więcej wyzwalaczy w łańcuchu zdarzeń.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);
Dodatkowy moduł
hstore
musi być zainstalowane. Szczegóły:- Jak ustawić wartość pola zmiennej złożonej za pomocą dynamicznego SQL
- Dynamiczne przekazywanie nazw kolumn dla zmiennej rekordu w PostgreSQL
Korzystanie z
hstore(text[], text[])
wariant tutaj, aby skonstruowaćhstore
wartość z wieloma polami w locie. -
Operator przypisania w plpgsql to
:=
: -
Zauważ, że użyłem nazwy kolumny
mod_datetime
zamiast mylącegomod_date
, ponieważ kolumna jest oczywiściesygnaturą czasową
a niedata
.
Dodałem kilka innych ulepszeń będąc przy tym. Sam wyzwalacz powinien wyglądać tak:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();