Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Работа с Oracle / Примеры применения триггеров.ppt
Скачиваний:
9
Добавлен:
28.06.2021
Размер:
300.03 Кб
Скачать

Типы триггеров

Часть кода между DECLARE и END имя_триггера

обычный базовый блок PL/SQL.

Различные триггерные события можно комбинировать с помощью оператора OR:

DELETE OR INSERT остальные_операторы

При использовании UPDATE можно указать список столбцов:

UPDATE ОF столбец_1, столбец_2, ...

Типы триггеров

При использовании UPDATE обращение к новой и старой строкам выполняется с помощью слов NEW и OLD, предваренных двоеточием.

: OLD.имя_столбца даст значение, которое столбец имел до обновления.

В триггерном ограничении имена OLD и NEW используются без двоеточий.

Пример триггера

В демонстрационной БД таблица Orders не хранит сумму заказа, которая является производной величиной (o_number * b_price).

Можно создать в этой таблице столбец o_summa, разре- шив для него значения NULL.

На таблицу Orders устанавливается триггер, который перед вставкой или обновлением заказа автоматически вычисляет сумму заказа и заносит в соответствующий столбец.

Пример триггера

CREATE OR REPLACE TRIGGER ord_summa BEFORE INSERT OR UPDATE

ON Orders

FOR EACH ROW DECLARE

price NUMBER(7, 2);

BEGIN

SELECT b_price INTO price FROM Books WHERE Books.book_ID = :NEW.o_book_ID ; :NEW.o_summa := : NEW . o_number * price ;

END ord_summa;

Модификация триггеров

Для триггеров (как и для представлений) не существует команды модификации. Старый триггер заменяется новым с помощью команды CREATE OR REPLACE TRIGGER.

Триггер можно удалить, выдав команду :

DROP TRIGGER имя_триггера;

Существующие триггеры можно деактивизировать и повторно активизировать, используя команды:

ALTER TRIGGER имя_триггера DISABLE ;

ALTER TRIGGER имя_триггера ENABLE ;

Тонкости, касающиеся триггеров (1)

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

В триггере, запускаемом оператором INSERT, имеет смысл обращаться только к новым значениям столбцов. Поскольку INSERT создает строку, старым значением всегда будет NULL.

В триггере, запускаемом оператором UPDATE, можно обращаться к старым и новым значениям столбцов. Это касается как BEFORE, так и AFTER-триггеров.

Тонкости, касающиеся триггеров (2)

В триггере, запускаемом оператором DELETE, следует обращаться только к старым значениям столбцов. Уда- ленная строка перестает существовать, и новым значе- нием всегда будет NULL. Однако значения :NEW нельзя модифицировать. Если вы попытаетесь это сделать, будет выдано сообщение об ошибке ORA-4084.

В теле триггера нельзя использовать операторы

ROLLBACK, COMMIT и SAVEPOINT.

При возникновении необрабатываемых исключений производится откат всех изменений, включая те, которые были выполнены запускающим оператором.

Тонкости, касающиеся триггеров (3)

Если для одного триггерного события определено более одного триггера, то порядок их срабатывания не определен.

Когда триггер пытается прочитать таблицу, а затем запи- сать в нее данные, возбуждается исключение «мутирующей таблицы». Oracle запретила операции, при которых таблица просто блокируется, а не изменяется. Следует создать вто- рую таблицу с копиями столбцов, которые триггер должен прочитать из главной таблицы. Триггер получает значения из второй таблицы, а затем выполняет действия с первой таблицей (важно обеспечить синхронизацию таблиц). Все операции INSERT, UPDATE и DELETE над главной табли- цей должны отражаться триггером на второй таблице.

Пример триггера (1)

CREATE OR REPLACE TRIGGER proverka BEFORE UPDATE

ON Orders

FOR EACH ROW DECLARE

no_name_change EXCEPTION; BEGIN

IF (:NEW.o_book_ID <> :OLD.o_book_ID) THEN

RAISE no_name_change; END IF;

Пример триггера (2)

EXCEPTION

WHEN no_name_change THEN

dbms_output.put_line('Изменение вида товаров в заказах запрещено');

dbms_output.put_line('Прервано и возвращены старые значения');

:NEW.order_ID := :OLD.order_ID; :NEW.o_user_ID := :OLD.o_user_ID; :NEW.o_book_ID := :OLD.o_book_ID; :NEW.o_time := :OLD.o_time; :NEW.o_number := :OLD.o_number;

END proverka;