Опубликован: 02.08.2007 | Доступ: свободный | Студентов: 3892 / 754 | Оценка: 4.55 / 4.39 | Длительность: 27:09:00
ISBN: 978-5-9556-0111-3
Лекция 12:

Разработка серверного кода

Для работы этого триггера проектировщик базы данных должен предусмотреть таблицу 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;

Проектировщик базы данных принимает решения о создании триггеров, проектирует их код и создает их в базе данных. Фактически, триггер базы данных - это хранимая процедура, которая связана с таблицей базы данных. Она автоматически запускается, когда над таблицей выполняется команда, контролируемая триггером. При создании триггеров проектировщик должен четко представлять цели создания триггера, поскольку они могут оказывать влияние и на структуру, и на производительность базы данных. Триггеры могут быть созданы, в частности, для решения таких задач, как:

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

Литература: [13], [20], [23], [38], [39], [45].

Александра Каева
Александра Каева
Михаил Забелкин
Михаил Забелкин