Możesz użyć format()
aby znacznie ułatwić tworzenie dynamicznego zapytania SQL, ponieważ automatycznie zajmie się ono poprawnie identyfikatorami i literałami. Jedną z rzeczy, które ludzie zwykle przeoczają, jest to, że możesz rozwinąć pojedyncze wyrażenie rekordu do wszystkich jego kolumn za pomocą (...).*
- działa to również w przypadku NEW
i OLD
rejestrować zmienne w wyzwalaczu, np. select (new).*
Możesz także przekazać zmienne do dynamicznego SQL za pomocą using
słowo kluczowe execute
oświadczenie. Nie ma potrzeby konwertowania rekordu tam iz powrotem między rekordem a reprezentacją tekstową.
Korzystając z tej możliwości, można uprościć funkcję wyzwalania do:
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;
Używanie symboli zastępczych, takich jak %I
i %L
umożliwia również jednokrotne zdefiniowanie rzeczywistego kodu SQL i ponowne jego wykorzystanie. Te "parametry" są zastępowane przez format()
funkcja (która zachowuje $1
)
Zwróć uwagę na użycie ($1).*
wewnątrz ciągu SQL. To sprawi, że execute
instrukcja rozwiń parametr rekordu $1
do wszystkich jego kolumn. Sam rekord jest przekazywany „natywnie” za pomocą USING
słowo kluczowe.
Użycie INSERT
bez docelowej listy kolumn (insert into some_table ...
zamiast insert into some_table (col1, col2, ...) ...
) jest dość delikatną rzeczą do zrobienia. Jeśli źródło i cel nie pasują do siebie, wstawienie może dość łatwo zawieść. .
Jeśli nie uruchamiasz masowego raportowania w tabelach audytu (gdzie posiadanie wyraźnych nazw kolumn byłoby znacznie bardziej wydajne), możesz pomyśleć o bardziej ogólnym wyzwalaczu audytu używającym JSON
lub HSTORE
kolumna do przechowywania całego rekordu. Dostępnych jest kilka gotowych wyzwalaczy audytu:
- http://okbob.blogspot. de/2015/01/most-simply-implementation-of-history.html
- https://github.com/wingspan/wingspan-auditing
- https://www.cybertec-postgresql.com /pl/śledzenie-zmian-w-postgresql/
- https://wiki.postgresql.org/wiki/Audit_trigger_91plus