
- •Лабораторная работа № 11 Триггеры и хранимые процедуры. Цель работы
- •Ход работы
- •Методические указания Алгоритмический язык хранимых процедур и триггеров.
- •Триггеры.
- •Обеспечения каскадных воздействий с помощью триггеров.
- •Иные применения триггеров.
- •Хранимые процедуры.
- •Хранимая процедура создается оператором
- •Примеры хранимых процедур.
- •Пример script-файла.
- •Отчет должен содержать:
Иные применения триггеров.
С помощью триггеров можно вести журнал наблюдений за изменением информации в БД. Журнал изменений в БД представляет собой таблицу БД, в которой фиксируются действия над всей базой данных или отдельными ее таблицами. В многопользовательских системах ведение такого журнала позволяет определить источник недостоверных или искаженных данных.
Триггеры активно используются для реализации бизнес-правил. В частности, это может быть установка с помощью генераторов уникальных значений индексных полей, накапливание статистики в других таблицах и многое другое. К сложностям, возникающим при реализации бизнес-правил при помощи триггеров, следует отнести неразвитость средств отладки логики кода, составляющего тело триггеров.
Хранимые процедуры.
Хранимая процедура - это модуль, написанный на процедурном языке InterBase и хранящийся в базе данных как метаданные (то есть как данные о данных). Хранимую процедуру можно вызывать из приложения.
Существует две разновидности хранимых процедур:
процедуры выбора;
процедуры действия.
Процедуры выбора могут возвращать более одного значения. В приложении имя хранимой процедуры выбора подставляется в оператор SELECT, с которым мы познакомимся позднее вместо имени таблицы или обзора.
Процедуры действия вообще могут не возвращать данных и используются для реализации каких-либо действий.
Хранимым процедурам можно передавать параметры и получать обратно значения параметров, измененные в соответствии с алгоритмами хранимых процедур.
Хранимая процедура создается оператором
CREATE PROCEDURE ИмяПроцедуры
[(входной_параметр тип_данных [, входной_параметр тип_данных... ])]
[RETURNS
(выходной_параметр тип_данных [, выходной_параметр тип_данных ...])] AS
<тело процедуры>;
Входные параметры служат для передачи в процедуру значений из вызывающего приложения. Изменять значения входных параметров в теле процедуры бессмысленно: эти изменения будут забыты после окончания работы процедуры.
Выходные параметры служат для возврата результирующих значений. Значения выходных параметров устанавливаются в теле процедуры и после окончания ее работы передаются в вызывающее приложение.
И входные, и выходные параметры могут быть опущены, если в них нет необходимости.
Тело процедуры имеет формат
[<объявление локальных переменных процедуры>]
BEGIN
< оператор>
[<оператор> ...]
END
Примеры хранимых процедур.
Хранимая процедура FindAuthorName возвращает в выходном параметре InAuthorName имя автора книги, код которого передается во входном параметре InAuthorCode:
CREATE PROCEDURE FindAuthorName
(InAuthorCode INTEGER)
RETURNS(InAuthorName CHAR(30))
AS
BEGIN
SELECT Name
FROM BookAuthors
WHERE Code = :InAuthorCode
INTO InAuthorName;
SUSPEND;
END
Заметим, что в приведенной процедуре за ненадобностью отсутствует определение локальных переменных. С оператором SELECT мы познакомимся позднее.
В логике хранимой процедуры можно проверять правила целостности и генерировать ошибку, если клиент запрашивает выполнение запрещенной операции. Например, ниже показан текст хранимой процедуры, выполняющей добавление новой записи в таблицу Books, которое произойдет только тогда, когда код автора книги будет найден в таблице Books. Если операция недопустима, после генерации соответствующей исключительной ситуации выполнение процедуры прекращается без добавления новой записи.
CREATE EXCEPTION AuthorNotFound "Автор книги не найден.";
CREATE PROCEDURE AddRecordInBooks
/*Процедура выполняет добавление новой записи в таблицу Books,
которое произойдет только тогда, когда код автора книги будет
найден в таблице Books. Если операция недопустима, после генерации
соответствующей исключительной ситуации выполнение процедуры
прекращается без добавления новой записи.*/
(AddAuthorCode INTEGER,
AddName CHAR (200),
AddIssueYear DATE,
AddDrawing INTEGER,
AddUDK CHAR (20),
AddCipher CHAR (30))
AS
DECLARE VARIABLE FindAuthorCode INTEGER;
BEGIN
SELECT COUNT(Code)
FROM BookAuthors
WHERE Code = :AddAuthorCode
INTO :FindAuthorCode;
/*В переменную помещаем результат поиска кода автора в таблице
BookAuthors.*/
IF (FindAuthorCode = 0) THEN
/*В таблице BookAuthors заданного кода автора книги не обнаружено.*/
BEGIN
EXCEPTION AuthorNotFound;
SUSPEND; END
ELSE
/*В таблице BookAuthors обнаружен заданный код автора книги.*/
BEGIN
INSERT INTO Books
(Code, Name, AuthorCode, IssueYear,
Drawing, UDK, Cipher)
VALUES
(GEN_ID(BooksCode, 1),
:AddName,
:AddAuthorCode,
:AddIssueYear,
:AddDrawing,
:AddUDK,
:AddCipher);
SUSPEND;
END
END
Исключительные ситуации определяются с помощью оператора CREATE EXCEPTION, как показано в листинге. Для генерации исключительной ситуации внутри хранимой процедуры используется следующий синтаксис:
EXCEPTION ExceptionName;
Если необходимо выполнить несколько проверок, тогда все требуемые проверки должны выполняться внутри данной хранимой процедуры. В результате, любое использующее эту хранимую процедуру клиентское приложение будет придерживаться одних и тех же ограничений целостности данных.
Процедуру AddRecordInBooks вызывают из клиентского приложения. Для проверки правильности работы процедуры средствами утилиты WISQL в командной ее части можно выполнить такую команду:
EXECUTE PROCEDURE AddRecordInBooks(1, 'Методы оптимального
управления', '01/01/2002', 10000, '681.513.5', '681.513.5:/А')
После ее выполнения в таблицу Books будет добавлена новая запись со значениями полей, переданными процедуре AddRecordInBooks в качестве параметров. Если вместо существующего значения кода автора (первый передаваемый параметр) подставить значение, которого нет в таблице BookAuthors, то новая запись в таблицу Books добавлена не будет, и на экран будет выведено сообщение «Statement failed, SQLCODE = -836». Нажав кнопку Details, Вы увидите причину возникновения этого сообщения:
Необходимо отметить, что для того чтобы в таблицу Books не были добавлены записи с кодом автора книги, которого нет в таблице BookAuthors необходимо определить соответствующий триггер, срабатывающий по событию BEFORE INSERT. Он приведен в примере SCRIPT-файла после процедуры AddRecordInBooks.