Триггеры

Триггером в СУБД ЛИНТЕР называется хранимая процедура, которая вызывается на выполнение ядром СУБД автоматически при наступлении в БД события, на которое настроен триггер.

События, на которое может быть настроен триггер, делятся на события обработки данных и системные события. В качестве события на обработку данных для триггера может выступать модификация (INSERT, DELETE или UPDATE) некоторой таблицы. В качестве системного события может быть событие регистрации пользователя. Триггер может вызываться один раз на весь SQL-оператор или на каждую операцию, выполняемую с записью таблицы. Триггеры различаются по времени срабатывания: до выполнения операции с записью (BEFORE), после выполнения операции (AFTER) и вместо выполнения операции (INSTEAD OF).

Тело триггера представляет собой исходный текст на процедурном языке, т.е. оно может включать декларации, исполняемые операторы и блок обработки исключений. В теле триггера разрешены любые операторы, в том числе, исполнение SQL-запросов, вызов хранимых процедур и т.д.

Триггеры типа INSTEAD OF применимы только к базовым таблицам и не применимы к представлениям.

В теле триггера, вызываемого на каждую строку (FOR EACH ROW) доступны специальные переменные с префиксом по умолчанию OLD и NEW, содержащие старое и новое значение строки. Обе эти переменные – структуры (т.е. с точки зрения языка хранимых процедур – курсорные переменные), включающие столбцы тех же имен и типов, что и обрабатываемая триггером таблица.

В зависимости от вида триггера эти переменные определяются следующим образом:

  • в триггере на INSERT доступна только переменная NEW; она содержит все значения, которые должны быть занесены в новую строку (если триггер BEFORE), или которые уже занесены (если триггер AFTER); при этом в триггере BEFORE допустимо присвоить полям переменной NEW новые значения, переопределив, таким образом, исходное поведение INSERT;

  • в триггере на UPDATE переменная NEW содержит значение, которое должно содержаться в строке после обновления (если триггер BEFORE), или которое уже там содержится (если триггер AFTER); при этом в триггере UPDATE допустимо присвоить полям переменной NEW новые значения, переопределив, таким образом, исходное поведение UPDATE; переменная OLD всегда содержит все значения, которые были в строке до обновления;

  • в триггере на DELETE доступна только переменная OLD; она содержит все значения удаляемой строки.

Кроме изменения значений переменной NEW, триггер BEFORE … FOR EACH ROW также может повлиять на ход выполнения SQL-запроса путем запрета операции. Для этого триггер должен вернуть логическое значение FALSE или завершиться с исключением. В такой ситуации конкретная строка, обработанная триггером, пропускается (не вставляется, не обновляется или не удаляется). Все остальные строки продолжают обрабатываться. Таким образом, в результате действия триггеров может оказаться, что часть строк, которые должны быть обработаны SQL-запросом, из этой обработки будут исключены. В этом случае количество реально обработанных строк можно получить с помощью соответствующих вызовов СУБД ЛИНТЕР.

СУБД ЛИНТЕР позволяет завершить и откатить весь SQL-оператор из триггера, вернув пользователю заданный код завершения.

С помощью триггеров можно снабдить СУБД такими возможностями, как альтернативный аудит, основанный на значениях данных, комплексный контроль безопасности и сложные правила целостности. Например, можно создать триггер, который будет позволять модифицировать некоторую таблицу лишь в заданный период времени.

Примечание

Хотя триггеры БД позволяют определять и вводить в действие правила целостности, они не эквивалентны этим правилам, а дополняют и/или расширяют их. Например, триггер, определенный для введения в действие правила целостности, не проверяет данные, уже загруженные в таблицу. Поэтому рекомендуется использовать триггеры вместо ограничений целостности только тогда, когда ограничение целостности не может быть реализовано подходящим правилом целостности.

Для поддержки триггеров должны существовать системные таблицы $$$TRIG и $$$PROC (создаются при выполнении SQL-скрипта systab.sql).