Введение в модель данных SQL

       

Выполнение триггеров


При выполнении каждого триггера система устанавливает контекст выполнения триггера. Выполнение любого оператора SQL, обновляющего базовую таблицу базы данных, может привести к срабатыванию одного или нескольких триггеров, а выполнение операторов SQL, содержащихся в триггерах, может привести к обновлению других базовых таблиц. Эти "внутритриггерные" (инициируемые) операторы выполняются в контексте текущего триггера, но их выполнение может привести к срабатыванию других триггеров. Для каждого из "вторичных" триггеров образуется собственный контекст выполнения, позволяющий определить их действия точно и независимо от действий первого набора триггеров. Выполнение вторичных триггеров может привести к срабатыванию "третичных" триггеров и т.д. - допускается произвольная глубина вложенности. Для каждого триггера на каждом уровне образуется собственный контекст.

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

Обсудим понятие контекста триггера немного более подробно. Предположим, что в нашей базе данных EMP-DEPT-PRO должно поддерживаться правило, в соответствии с которым каждый служащий, становящийся руководителем проекта, автоматически получает прибавку к заработной плате в 10 000 руб. (Для простоты будем считать, что снятие служащего с должности руководителя проекта не приводит к автоматическому изменению его зарплаты и что для каждого служащего, являющегося руководителем проекта, определен номер отдела, в котором он работает.) Тогда мы могли бы определить триггер CHANGE_MNG_NO следующим образом:

CREATE TRIGGER CHANGE_MNG_NO AFTER UPDATE OF PRO_MNG ON PRO FOR EACH ROW UPDATE EMP SET EMP_SAL = EMP_SAL + 10000.00 WHERE EMP_NO = PRO_MNG;

Но очевидно, что для поддержания корректности данных в таблице DEPT нам требуется триггер, условием срабатывания которого было бы изменение значений столбца EMP_SAL в таблице EMP. Определим соответствующий триггер DEPT_CORRECTION_1:


CREATE TRIGGER DEPT_CORRECTION_1 AFTER UPDATE OF EMP_SAL ON EMP REFERENCING OLD ROW AS OLD_EMP NEW ROW AS NEW_EMP FOR EACH ROW UPDATE DEPT SET DEPT_TOTAL_SAL = DEPT_TOTAL_SAL + NEW_EMP.EMP_SAL - OLD_EMP.EMP_SAL WHERE EMP.DEPT_NO = DEPT.DEPT_NO;

Пусть теперь выполняется операция

UPDATE PRO SET PRO_MNG = 4455 WHERE PRO_NO = 554;

Сразу после выполнения этой операции сработает триггер CHANGE_MNG_NO. Этот триггер будет выполняться в контексте, который мы для удобства назовем контекстом CMN. Заметим, что исходный оператор модификации в действительности изменяет только одну строку таблицы PRO, но триггеру CHANGE_MNG_NO это неизвестно, и он будет работать так, как если бы изменялось произвольное число строк таблицы PRO.

Выполнение операции модификации таблицы EMP приведет к срабатыванию триггера DEPT_CORRECTION_1. В этот момент контекст CMN будет "упрятан в стек", образуется и станет активным контекст следующего триггера - контекст DR1. После завершения выполнения этого триггера контекст DR1 больше не требуется, и он ликвидируется, а из стека восстанавливается контекст CMN, в котором и будет завершено выполнение триггера CHANGE_MNG_NO.

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



  • триггерноесобытие - INSERT, UPDATE или DELETE;
  • имя предметной таблицы триггера;
  • имена столбцов предметной таблицы, специфицированных в определении триггера (только для триггеров по UPDATE);
  • набор переходов (представление всех строк, вставляемых в предметную таблицу, модифицируемых в ней или удаляемых из нее), список всех триггеров уровня STATEMENT, уже выполненных в некотором (не обязательно активном) контексте выполнения, и список всех триггеров уровня ROW, уже выполненных в некотором (не обязательно активном) контексте выполнения, и строк, над которыми эти триггеры выполнялись.


Отслеживание уже выполненных триггеров ведется для предотвращения многократного выполнения одного и того же триггера в результате возникновения одного события, что могло бы потенциально привести к зацикливанию выполнения системы триггеров.

При создании контекста выполнения триггера его набор изменений состояния изначально пуст. В набор изменений состояния добавляется каждое встречающееся "новое" изменение состояния, в котором не дублируются триггерное событие существующего изменения состояния, имя предметной таблицы и имена столбцов предметной таблицы. Набор переходов каждого изменения состояния изначально пуст, и переходы добавляются при каждом обновлении предметной таблицы, ассоциированной с изменением состояния (включая обновления, производимые ссылочными действиями).


Содержание раздела