Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы / Лаб7-8.docx
Скачиваний:
278
Добавлен:
11.06.2017
Размер:
50.35 Кб
Скачать

ФЕДЕРАЛЬНОЕ АГЕНТСТВО СВЯЗИ

Федеральное государственное образовательное бюджетное учреждение

высшего профессионального образования

Московский технический университет связи и информатики

Кафедра интеллектуальных систем управления и автоматизации

Лабораторная работа №7-8

по дисциплине

Базы данных

Москва 2017

Триггеры

Триггеры в Oracle — это процедуры на языке Java или SQL, которые вызываются при выполнении определенных действий с базой данных. Oracle поддерживает несколько типов триггеров: одни запускаются командами SQL, создающими в базе данных новые структуры, например таблицы, другие запускаются единожды на уровне таблицы, когда происходит изменение строк таблицы, третьи запускаются по одному разу для каждой измененной строки. Последние называются строчными триггерами (row triggers); их мы и будем рассматривать здесь. Oracle поддерживает три вида триггеров: предваряющие (триггеры BEFORE), завершающие (триггеры AFTER) и замещающие (триггеры INSTEAD OF).

Пример предваряющего триггера

В листинге 1 показан предваряющий триггер, который используется для задания значения строки перед обновлением. Чтобы использовать этот триггер, создаем сначала в таблице TRANSACTION новый столбец под именем AskingPrice типа Number(7, 2).

В листинге 1 триггер New_Price определен фразой

Before Insert or Update of AcquisitionPrice ON TRANSACTION.

Эта фраза, являясь правильной, содержит неопределенность. Она означает «ПЕРЕД (любой) вставкой в транзакции или ПЕРЕД обновлением AcquisitionPrice в транзакции запустить триггер». Таким образом, триггер будет запущен при любой вставке или при обновлении столбца AcquisitionPrice. Обновления других столбцов не вызовут запуска триггера.

SQL> describe TRANSACTION

Name Null? Type

----------------------------------------- ------------ ----------------------------

TRANSACTIONID NOT NULL NUMBER(38)

DATEACQULRED NOT NULL DATE

ACQUISITIONPRICE NUMBER(7,2)

PURCHASEDATE DATE

SALESPRICE NUMBER(7,2)

CUSTOMERID NUMBER(38)

WORKID NOT NULL NUMBER(38)

SQL> alter table TRANSACTION

2 add AskingPrice Number(7,2);

Table altered.

SQL> describe TRANSACTION

Name Null? Type

----------------------------------------- -------------- ----------------------

TRANSACTIONID NOT NULL NUMBER(38)

DATEACQULRED NOT NULL DATE

ACQUISITIONPRICE NUMBER(7,2)

PURCHASEDATE DATE

SALESPRICE NUMBER(7,2)

CUSTOMERID NUMBER(38)

WORKID NOT NULL NUMBER(38)

ASKINGPRICE NUMBER(7,2)

Фраза FOR EACH ROW (для каждой строки) указывает, что данный триггер является строчным. Логика его работы проста: новое значение AskingPrice вычисляется как удвоенное новое значение AcquisitionPrice.

Префикс new доступен только для триггеров. Он обозначает новое значение столбца в команде INSERT или UPDATE. Так, new.AcquisitionPrice обозначает новое значение AcquisitionPrice (заданное пользователем). Для обновлений и удалений существую также префикс old, обозначающий значение столбца до выполнения команды UPDATE или DELETE.

Создадим триггер в файле Trig1.sql. Запустим файл в SQL Plus - триггер скомпилируется. Если не будет ошибок компиляции, триггер будет сохранен в базе данных и станет активным. Обновим столбец AcquisitionPrice и затем выберем строки, которые мы обновили. Значение столбца AskingPrice будет задано триггером.

Листинг 1. Предваряющий триггер New_Price

CREATE OR REPLACE TRIGGER New_Price

BEFORE INSERT OR UPDATE of Acquisitionprice ON TRANSACTION

FOR EACH ROW

/* Устанавливаем новое значение AskingPrice перед вставкой или обновлением */

BEGIN

:new.AskingPrice := :new.AcquisitionPrice * 2;

END;

SQL> start c:\tmp\trig1.sql;

Trigger created.

SQL> select * from transaction;

SQL> update transaction

2 set acquisitionprice=acquisitionprice

3 where acquisitionprice is not null;

3 rows updated.

SQL> select * from transaction;

Пример завершающего триггера

В листинге 2 показан пример завершающего триггера. Логика его такова: View Ridge определяет произведение, предназначенное для продажи, как любое произведение, имеющее строку в таблице TRANSACTION с пустым значением CustomerID. Задача этого триггера — гарантировать, что такая строка в таблице TRANSACTION будет существовать, когда в базу данных будет записываться произведение. Этот триггер, запускаемый при создании строки в таблице WORK, проверяет таблицу TRANSACTION и не производит никаких действий, если находит в ней подходящую строку.

Листинг 2. Завершающий триггер On_Work_lnsert

CREATE OR REPLACE TRIGGER On_WORK_Insert

AFTER INSERT ON WORK

FOR EACH ROW

DECLARE

rowcount integer(2);

BEGIN

/*Считаем доступные строки*/

SELECT Count (*) INTO rowcount

FROM TRANSACTION

WHERE CustomerID IS NULL AND WorkID=:new.WorkID;

IF rowcount > 0 Then

DBMS_OUTPUT.PUT_LINE ('Подходящая строка в таблице

TRANSACTION существует -- никаких действий не предпринято.');

RETURN;

ELSE /*нужно добавить новую строку*/

INSERT INTO TRANSACTION (TransactionID, DateAcqulred,

WorkID)

VALUES (TransID.NextVal, SysDate, :new.WorkID);

END IF;

END;

SQL> select * from work;

WORKID DESCRIPTION TITLE COPY ARTISTID

---------- -------------------- ------------------------ -------- -------------

500 1892 Vladimirka 1 8

501 1912 Gitara_i_scripka 1 9

502 1903 Starii_gitarist 1 9

SQL> start c:\tmp\trig2.sql

Trigger created.

SQL> insert into WORK (WorkID, Title, Copy, ArtistID)

2 values (WorkID.NextVal, 'Dub','REP',8);

1 row created.

SQL> select * from work;

WORKID DESCRIPTION TITLE COPY ARTISTID

---------- -------------------- ------------------------ -------- -------------

500 1892 Vladimirka 1 8

501 1912 Gitara_i_scripka 1 9

502 1903 Starii_gitarist 1 9

520 Dub 1 8

SQL> select * from transaction;

Пример замещающего триггера

Замещающие триггеры используются для обновления представлений,

Рассмотрим представление, определенное в листинге 3. Оно соединяет в себе

четыре таблицы и, как представление соединения, не может быть обновлено без

помощи соответствующего триггера.

Листинг 3. Определение представления CustomerPurchases

CREATE VIEW CustomerPurchases AS

SELECT CUSTOMER.Name CustName, Copy, Title, ARTIST.Name

ArtistName

FROM CUSTOMER, TRANSACTION, WORK, ARTIST

WHERE CUSTOMER.CustomerID = TRANSACTION.CustomerID AND

TRANSACTION.WorkID = WORK.WorkID AND

WORK.ArtistID = ARTIST.ArtistID;

Создать представление и вывести содержащиеся в нем данные.

Обратите внимание на фразу SELECT в определении этого представления. Она задает синонимы для столбцов CUSTOMER.Name (синоним CustName) и ARTIST.Name (синоним ArtistName). Если бы это не было сделано, в представлении оказалось бы одна столбца с именем Name, а такое недопустимо.

Исследуйте данные выведенные в представлении; подумайте, что должно произойти, когда пользователь попытается обновить столбец Title. Название «Mystic Fabric» фигурирует в трех строках, но в таблице WORK имеется только две строки с таким названием.

Невозможно написать для СУБД обобщенный код, который бы корректно обрабатывал каждую возможную ситуацию. Замещающие триггеры позволяют разработчику задать действия, которые необходимо предпринять при попытке обновить представление в конкретном приложении. В листинге 4 показан пример такого триггера, который обрабатывает обновления столбца Title представления CustomerPurchases. Поскольку замещающие триггеры, в отличие от предваряющих, не могут содержать фразу UPDATE OF, мы должны написать код, определяющий, был ли изменен столбец Title.

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