Можете да използвате format()
за да направи създаването на динамична SQL заявка много по-лесно, тъй като автоматично ще се справи правилно с идентификатори и литерали. Едно нещо, което хората обикновено пренебрегват, е, че можете да разширите израз на един запис до всичките му колони, като използвате (...).*
- това работи и за NEW
и OLD
запис на променливи в тригер, напр. select (new).*
Можете също да подадете променливи към динамичен SQL с using
ключова дума на execute
изявление. Няма нужда да конвертирате записа напред и назад между запис и текстово представяне.
Използвайки тази възможност, вашата тригерна функция може да бъде опростена до:
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;
Използване на контейнери като %I
и %L
също така дава възможност да се дефинира действителният SQL само веднъж и да се използва повторно. Тези „параметри“ се заменят с format()
функция (която запазва $1
)
Обърнете внимание на използването на ($1).*
вътре в SQL низа. Това ще направи execute
израз разгънете параметъра на запис $1
към всички негови колони. Самият запис се предава "нативно" с USING
ключова дума.
Използването на INSERT
без списък с целеви колони (insert into some_table ...
вместо insert into some_table (col1, col2, ...) ...
) е доста крехка работа. Ако източникът и целта не съвпадат, вмъкването може да се провали доста лесно. .
Ако не изпълнявате масово отчитане на таблиците за проверка (където наличието на изрични имена на колони би било много по-ефективно), може да искате да помислите за по-общ тригер за проверка, използвайки JSON
или HSTORE
колона за съхраняване на целия запис. Налични са няколко готови задействания за одит:
- 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