Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СУБД Oracle / Лекции / Лек_ORAC / LA / Триггеры.doc
Скачиваний:
53
Добавлен:
16.04.2013
Размер:
81.41 Кб
Скачать

Особенности, связанные с триггерами dml-событий (insert,updatEилиDelete).

Предложение INSTEADOFуказывает, что триггер должен выполнятьсявместособытия.

Предложение FOREACHROW– определяет строчный триггер (rowtrigger), который запускается один раз для каждой обработанной строки. По умолчанию создаётся операторный триггер (statementtrigger), который запускается при выполнении соответствующей инструкции, даже если ни одна строка не затронута. (Для этих понятий применяются также термины: триггер уровня строки и триггер уровня инструкций.)

Пример создания операторного триггера BEFORE.

SQL> CREATE OR REPLACE TRIGGER secure_emp

2Before insert on emp

3BEGIN

4IF (TO_CHAR (sysdate,'DY') IN ('SAT','SUN'))

5OR (TO_CHAR(sysdate,'HH24') NOT BETWEEN

6 '08'AND '18')

7THEN RAISE_APPLICATION ERROR (-20500,

8 'You may only insert into EMP during normal

9 hours. ') ;

10END IF;

11 END;

12 /

И пример срабатывания этого триггера для схемы “scott”.

SQL> INSERT INTO emp (empno, ename, deptno)

2 VALUES (7777, 'BAUWENS', 40);

INSERT INTO emp (empno, ename, deptno)

*

ERROR at line 1:

ORA-20500: You may only insert into EMP during normal

hours.

ORA-06512: at "SCOTT.SECURE_EMP", line 4

ORA-04088: error during execution of trigger

'SCOTT.SECURE EMP'

При попытке вставить строку в таблицу EMPв нерабочие часы выдается сообщение “YoumayonlyinsertintoEMPduringnormalhours” (“Вставка в таблицуEMPвозможна только в обычные рабочие часы”).

Триггеры уровня строки имеют программный доступ к значениям записи до, и после измененияданных через псевдозаписи. По умолчанию имена этих псевдозаписей “:new” и “:old”. Эти записи подобны записям, определённым с помощью атрибута %ROWTYPE, но отличаются тем, что в них нельзя ссылаться на столбцы типаLONGиLONGROW. Для псевдозаписей (в отличие от обычных записей) нельзя использовать агрегатное присваивание – значение полям можно назначать только индивидуально.

Примечание. Обозначения “:new” и “:old” предшествующие имени поля также называют квалификаторами.

Примечание. В триггерахINSERTзначения всех полей старой записи –NULL, а в триггерахDELETEзначения всех полей новой записи –NULL.

Предложение REFERENCINGдаёт возможность использовать собственные (а не заданные по умолчанию) имена для прежней и новой записи.

Пример. На таблице EMP создается триггер, вставляющий строки в учетную таблицу AUDIT_EMP_VALUES. Эта таблица содержит сведения об операциях, выполненных пользователями с таблицей EMP. Триггер записывает значения нескольких столбцов до и после их изменения, используя в названиях столбцов квалификаторы OLD и NEW.

SQL>CREATE OR REPLACE TRIGGER audit_emp_values

2 After delete or insert or update on emp

3 FOR EACH ROW

4 BEGIN

5 INSERT INTO audit_emp_values (user_name,

6 timestamp, id, old_last_name, new_last_name,

7 old_title, new_title, old_salary, new_salary)

8 VALUES (USER, SYSDATE, :old.empno,:old.ename,

9 :new.ename,:old.job,:new.job,

10 :old.sal,:new.sal);

11 END;

12 /

Этот триггер можно было бы создать и используя предложение REFERENCINGследующим образом:

SQL>CREATE OR REPLACE TRIGGER audit_emp_values

2 AFTER DELETE OR INSERT OR UPDATE ON emp

3 REFERENCING OLD AS OLDR NEW AS NEWR

4 FOR EACH ROW

5 BEGIN

6 INSERT INTO audit_emp_values (user_name,

7 timestamp, id, old_last_name, new_last_name,

8 old_title, new_title, old_salary, new_salary)

9 VALUES (USER, SYSDATE, OLDR.empno,OLDR.ename,

10 NEWR.ename,OLDR.job,NEWR.job,

11 OLDR.sal,NEWR.sal);

12 END;

13 /

Замечание. Квалификаторыnewиoldмогут использоваться и в условии триггера (предложениеWHEN),однако здесь не используется лидирующее двоеточие. Например, триггер для вставки строк в таблицуEMPили для изменения поляSAL:

SQL>CREATE OR REPLACE TRIGGER derive_commission_pct

2 BEFORE INSERT OR UPDATE OF sal ON emp

3 FOR EACH ROW

4 WHEN (new.job = 'SALESMAN')

5 BEGIN

6 IF INSERTING THEN :new.comm := 0;

7 ELSE /* UPDATE of salary */

8 IF :old.comm IS NULL THEN

9 :new.comm := 0 ;

10 ELSE

11 :new.comm := :old.comm * (:new.sal/:old.sal);

12 END IF;

13 END IF;

14 END;

15 /

При создании триггера из нескольких событий, внутри тела триггера могут быть использованы триггерные предикаты INSERTING, UPDATINGили DELETING, чтобы выделить части триггера выполняемые для конкретного события.

Пример. Создание триггера, ограничивающего все DML-операции с таблицей EMP определенными рабочими часами с понедельника по пятницу.

SQL>CREATE OR REPLACE TRIGGER secure_emp

2 BEFORE INSERT OR UPDATE OR DELETE ON emp

3 BEGIN

4 IF (TO_CHAR (sysdate,'DY') IN ('SAT','SUN')) OR

5 (TO_CHAR(sysdate,'HH24')NOT BETWEEN'08'AND'48')THEN

6 IF DELETING THEN

7 RAISE_APPLICATION_ERROR (-20502, 'You may '||

8 'only delete from EMP during normal hours.');

9 ELSIF INSERTING THEN

10 RAISE_APPLICATION_ERROR (-20500, 'You may '||

11 'only insert into EMP during normal hours.');

12 ELSIF UPDATING ('SAL') THEN

13 RAISE_APPLICATION_ERROR (-20503, 'You may '||

14 'only update SAL during normal hours.');

15 ELSE

16 RAISE_APPLICATION_ERROR (-20504, 'You may '||

17 'only update EMP during normal hours.');

18 END IF;

19 END IF;

20 END;

21 /

Триггеры DML-событий нельзя создавать для системных объектов. Эти триггеры запускаются в таком порядке:

  1. Триггер BEFOREуровня инструкций.

  2. Для каждой строки, обрабатываемой инструкцией.

  3. Триггер BEFOREуровня строки.

  4. Сама инструкция, запускающая триггер.

  5. Триггер AFTERуровня строки.

  6. Триггер AFTERуровня инструкций.

Таким образом, по одной DML-команде могут выполняться до четырех типов триггеров (операторных и строчных, BEFOREиAFTER). Событие или команда, по которым срабатывает триггер, могут вызвать проверку соблюдения одного или нескольких правил целостности. Кроме того, триггеры могут вызывать каскадное срабатывание других триггеров (cascading triggers). Все действия и проверки, выполняемые в результате выполнения исходной SQL-команды, должны быть успешно завершены.

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

При проектировании триггеров руководствуйтесь следующими указаниями:

  • Используйте триггеры, чтобы обеспечить выполнение конкретных действий при каждой конкретной операции.

  • Используйте триггеры базы данных только для централизованных глобальных операций, которые должны быть выполнены для каждой команды, по которой срабатывает триггер, независимо от того, от какого пользователя или из какого приложения пришла эта команда.

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

  • Чрезмерное использование триггеров может привести к появлению сложных взаимозависимостей, сопровождение которых в больших приложениях может потребовать значительных усилий. Пользуйтесь триггерами только по необходимости и помните о рекурсивном и каскадном эффектах.

Хотя триггеры AFTERработают немного быстрее, чем -BEFORE, но, в отличие от последних, они не могут изменять новые значения записи. Поэтому триггерыAFTERлучше подходят для проверки данных, а триггерыBEFOREлучше подходят для коррекции изменения данных.

Пример триггера AFTER. Предположим, что имеется пользовательская учетная таблицаaudit_table, которая содержит имена всех пользователей и количество выполненных ими DML-операций. После того, как какой-либо пользователь обновил столбец SAL в таблице ЕМР, с помощью учетной таблицы производится проверка на то, что количество изменений оклада (v_salary_changes) не превысило максимально допустимое (v_max_changes) для этого пользователя (user).

SQL>CREATE OR REPLACE TRIGGER check_salary_count

Соседние файлы в папке LA