Разработка серверного кода
Для работы этого триггера проектировщик базы данных должен предусмотреть таблицу company_holidays, которая будет содержать список праздничных дней в организации. Триггер будет запускаться до выполнения (BEFORE) любых операции модификации данных DELETE, INSERT или UPDATE над таблицей EMPLOYEE.
Триггер выполняет следующие операции:
- Если текущий день является субботой или воскресеньем, то выдается сообщение об ошибке и никаких изменений в таблице не производится.
- Триггер сравнивает текущую дату с датами праздников, разрешенных в организации. Если текущая дата - праздник, то выдается сообщение об ошибке и никаких изменений в таблице не производится.
- Если текущее время не находится в интервале от 8 до 17 часов, то выдается сообщение об ошибке и никаких изменений в таблице не производится.
В качестве второго примера создадим строчный триггер SALARY_CHECK для таблицы EMPLOYEE, который будет гарантировать, что зарплата сотрудника будет находиться в пределах должностного оклада, когда добавляется новый сотрудник или у существующего меняется зарплата или должность.
Пример
CREATE TRIGGER salary_check BEFORE INSERT OR UPDATE OF sal, job ON employee FOR EACH ROW WHEN (new.job <> 'PRESIDENT') DECLARE minsal NUMBER; maxsal NUMBER; BEGIN /* Получить минимальные и максимальные ставки зарплаты для данной должности из таблицы SAL_GUIDE */ SELECT minsal, maxsal INTO minsal, maxsal FROM sal_guide WHERE job = :new.job; /* Если зарплата сотрудника находится вне пределов этого интервала, то генерировать ошибку. */ IF (:new.sal < minsal OR :new.sal > maxsal) THEN raise_application_error( -20601, 'Зарплата ' || :new.sal || ' выходит за пределы ставки по должности ' || :new.job || ' для сотрудника ' || :new.ename ); END IF; END;
Триггер является строчным триггером с временем действия до начала операции. Этот триггер запускается до вставки или обновления каждой строки таблицы EMPLOYEE, которые изменяют значения колонок SAL или JOB. Триггер SALARY_CHECK имеет ограничение: он предотвращает контроль зарплаты директора организации. Для каждой новой или обновляемой записи триггер делает следующее:
- выдает запрос к таблице salary_guide, чтобы получить минимальную и максимальную ставки зарплаты для указанной должности;
- если зарплата выходит за пределы полученного интервала, то выдается ошибка и операция прекращается.
Рассмотрим вопрос о том, как решение проектировщика базы данных о создании триггера может оказывать влияние на структуру базы данных. Если проектировщик базы данных принимает решение создать триггер второго примера в базе данных, он должен добавить в физическую схему базы данных команду создания таблицы salary_guide, например как показано ниже.
CREATE TABLE salary_guide ( job char(20) NOT NULL, min_sal dec(15,2), max_sal dec(15,2) );
Если эта таблица будет заполнена с помощью команды
INSERT INTO salary_guide VALUES(:1,:2,:3) \ Менеджер,2500000,10000000 Разработчик,1500000,2000000 Проектировщик,1000000,2000000 Кодировщик,500000,1000000 Тестировщик,500000,750000 Бухгалтер,1000000,1500000 Референт,500000,1000000 /
то нижеследующий оператор INSERT будет отвергнут:
INSERT INTO EMPLOYEE VALUES (2003, 'Прохоров', 'Андрей', 20, 'Менеджер', 09-05-66, 08-15-95, 12000000, 0, 0, 1 );
Приведем пример создания триггера для операции удаления в таблицах, связанных отношением "родитель-потомок". Предположим, что таблица JOB_TAB является родительской для таблицы EMPLOYEE. При удалении строк из таблицы JOB_TAB триггер будет проверять наличие зависимых строк в таблице EMPLOYEE и, при наличии последних, блокировать выполнение удаления с кодом ошибки 20000, определенной пользователем.
CREATE TRIGGER JOB_DEL BEFORE DELETE ON JOB_TAB FOR EACH ROW BEGIN Select job from employee where employee.job=Job IF NO_DATA_FOUND THEN raise_application_error(-20000, 'Строка не может быть удалена'); END IF' END;
Данный триггер для операции удаления не допустит нарушения ссылочной целостности. Заметим, что ссылочная целостность не была определена средствами СУБД в данном примере.
Триггеры в базе данных могут находиться в двух состояниях - активном и пассивном. В активном состоянии триггер всегда запускается, когда возникает событие, его инициирующее. В пассивном состоянии триггер не запускается, когда возникает связанное с ним событие. Когда триггер создается, СУБД переводит его в активное состояние автоматически. Триггер можно перевести в пассивное состояние и обратно командой SQL ALTER TABLE с опциями DISABLE и ENABLE или с предложениями DISABLE и ENABLE.
Для удаления триггера используется команда SQL DROP, как показано в примере ниже.
DROP TRIGGER JOB_DEL;
Проектировщик базы данных принимает решения о создании триггеров, проектирует их код и создает их в базе данных. Фактически, триггер базы данных - это хранимая процедура, которая связана с таблицей базы данных. Она автоматически запускается, когда над таблицей выполняется команда, контролируемая триггером. При создании триггеров проектировщик должен четко представлять цели создания триггера, поскольку они могут оказывать влияние и на структуру, и на производительность базы данных. Триггеры могут быть созданы, в частности, для решения таких задач, как:
- поддержка специального аудита и мониторинга таблиц базы данных на определенные события;
- автоматическое генерирование значений производных колонок в таблице;
- для организации сложных мер обеспечения безопасности доступа к данным;
- для поддержки бизнес-правил и ограничений предметной области;
- для поддержки репликации асинхронных таблиц.