На PL/Tcl можно написать триггерные процедуры. PostgreSQL требует, чтобы процедура, которая будет вызываться как триггерная, была объявлена как функция без аргументов и возвращала тип trigger
.
Информация от менеджера триггеров передаётся в тело процедуры в следующих переменных:
$TG_name
Имя триггера из оператора CREATE TRIGGER
.
$TG_relid
Идентификатор объекта таблицы, для которой будет вызываться триггерная процедура.
$TG_table_name
Имя таблицы, для которой будет вызываться триггерная процедура.
$TG_table_schema
Схема таблицы, для которой будет вызываться триггерная процедура.
$TG_relatts
Список языка Tcl, содержащий имена столбцов таблицы. В начало списка добавлен пустой элемент, поэтому при поиске в этом списке имени столбца с помощью стандартной в Tcl команды lsearch
будет возвращён номер элемента, начиная с 1, так же, как нумеруются столбцы в PostgreSQL. (В позициях удалённых столбцов также содержатся пустые элементы, так что нумерация следующих за ними атрибутов не нарушается.)
$TG_when
Строка BEFORE
, AFTER
или INSTEAD OF
, в зависимости от типа события триггера.
$TG_level
Строка ROW
или STATEMENT
, в зависимости от уровня события триггера.
$TG_op
Строка INSERT
, UPDATE
, DELETE
или TRUNCATE
, в зависимости от действия события триггера.
$NEW
Ассоциативный массив, содержащий значения новой строки таблицы для действий INSERT
или UPDATE
, либо пустой массив для DELETE
. Индексами в массиве являются имена столбцов. Столбцы со значениями NULL в нём отсутствуют. Для триггеров уровня оператора этот массив не определяется.
$OLD
Ассоциативный массив, содержащий значения старой строки таблицы для действий UPDATE
или DELETE
, либо пустой массив для INSERT
. Индексами в массиве являются имена столбцов. Столбцы со значениями NULL в нём отсутствуют. Для триггеров уровня оператора этот массив не определяется.
$args
Список на языке Tcl аргументов процедуры, заданных в операторе CREATE TRIGGER
. Эти аргументы также доступны под обозначениями $1
... $
в теле процедуры.n
Возвращаемым значением триггерной процедуры может быть строка OK
или SKIP
либо список пар имя столбца/значение. Если возвращается значение OK
, операция (INSERT
/UPDATE
/DELETE
), которая привела к срабатыванию триггера, выполняется нормально. Значение SKIP
указывает менеджеру триггеров просто пропустить эту операцию с текущей строкой данных. Если возвращается список, через него PL/Tcl передаёт менеджеру триггеров изменённую строку; содержимое изменённой строки задаётся именами и значениями столбцов в списке. Все столбцы, не перечисленные в этом списке, получают значения NULL. Возвращать изменённую строку имеет смысл только для триггеров уровня строки с порядком BEFORE
команд INSERT
и UPDATE
, в которых вместо заданной в $NEW
будет записываться изменённая строка; либо с порядком INSTEAD OF
команд INSERT
и UPDATE
, в которых возвращаемая строка служит исходными данными для предложений INSERT RETURNING
или UPDATE RETURNING
. В триггерах уровня строки с порядком BEFORE
или INSTEAD OF
команды DELETE
возврат изменённой строки воспринимается так же, как и возврат значения OK
, то есть операция выполняется. Для всех остальных типов триггеров возвращаемое значение игнорируется.
Список результатов можно создать из изменённого кортежа, представленного в виде массива, с помощью команды array get
языка Tcl.
Следующий небольшой пример показывает триггерную процедуру, которая ведёт в таблице целочисленный счётчик числа изменений, выполненных в строке. Для новых строк счётчик инициализируется нулевым значением, а затем увеличивается на единицу при каждом изменении.
CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS $$ switch $TG_op { INSERT { set NEW($1) 0 } UPDATE { set NEW($1) $OLD($1) incr NEW($1) } default { return OK } } return [array get NEW] $$ LANGUAGE pltcl; CREATE TABLE mytab (num integer, description text, modcnt integer); CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
Заметьте, что сама триггерная процедура не знает имени столбца; оно передаётся в аргументах триггера. Это позволяет применять эту триггерную процедуру для различных таблиц.