Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Архив / Пособие_Триггеры и процедуры (1)

.pdf
Скачиваний:
44
Добавлен:
14.05.2015
Размер:
666.86 Кб
Скачать

ПетрГУ, кафедра прикладной математики и кибернетики

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

1.Пользователь передает СУБД команду Update;

2.СУБД записывает новые значения записи из переменной NEW в обновляемую

таблицу;

3.СУБД заполняет переменные OLD и NEW;

4.СУБД вызывает триггер.

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

1.Пользователь передает СУБД команду Delete;

2.СУБД заполняет переменную OLD;

3.СУБД вызывает триггер;

4.СУБД удаляет запись из таблицы.

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

1.Пользователь передает СУБД команду Delete;

2.СУБД удаляет запись из таблицы;

3.СУБД заполняет переменную OLD;

4.СУБД вызывает триггер.

Удаление

DROP TRIGGER <имя триггера>

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

11

ПетрГУ, кафедра прикладной математики и кибернетики

6 Примеры реализации триггеров

Пример 1

Ограничение предметной области: стипендия студента не может быть увеличена более чем на 5% от предыдущей стипендии.

CREATE TRIGGER tgrStudentGrantUpdate

BEFORE UPDATE OF Grant

ON tblStudent

BEGIN

IF (NEW.Grant – OLD.Grant > 0.05 * OLD.Grant)

SET NEW.Grant = 1.05 * OLD.Grant

END

Триггер tgrStudentGrantUpdate создан для таблицы tblStudent. Триггер будет срабатывать до выполнения операции изменения данных, чтобы в таблицу были записаны уже корректные данные.

При вызове триггера СУБД создает две переменных: OLD, содержащую значения изменяемой записи до ее изменения, и NEW, содержащую значения изменяемой записи после ее изменения.

После вызова триггера в теле триггера проверяется условие о величине изменения стипендии. Если стипендия изменилась более чем на 5%, то триггер вносит поправку в данные – увеличивает стипендию только на 5% по сравнению с предыдущим значением стипендии студента. Это действие выполняется посредством записи правильного значения стипендии в переменную NEW.

Рассмотрим более детально работу триггера.

Пусть таблица tblStudent включает следующие записи: tblStudent

StudentId

StudentName

Grant

1023

Бобров А.А.

10000

1025

Мухина В.Н.

12000

1026

Лобов А.Г.

14000

Пусть пользователь отправил на выполнение следующую команду:

Update tblStudent Set Grant = 12000 Where StudentId = 1023

Прежде, чем выполнить эту команду СУБД вызовет триггер tgrStudentGrantUpdate. При этом СУБД создаст переменные OLD и NEW и наполнит их следующими

данными:

OLD

 

StudentId

StudentName

Grant

 

 

 

1023

Бобров А.А.

10000

 

 

 

 

 

 

 

 

 

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

12

ПетрГУ, кафедра прикладной математики и кибернетики

NEW

StudentId

StudentName

Grant

1023

Бобров А.А.

12000

Проверка условия дает истинное значение, и триггер в переменной NEW изменяет значение в поле Grant:

NEW

StudentId

StudentName

Grant

1023

Бобров А.А.

10500

Триггер заканчивает работу, и СУБД вносит изменения в таблицу для записи с идентификатором 1023, выбирая новые значения для записи из переменной NEW.

В результате в таблице tblStudent записи будут такими:

tblStudent

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

1023

Бобров А.А.

10500

 

1025

Мухина В.Н.

12000

 

1026

Лобов А.Г.

14000

Рассмотрим другую ситуацию.

 

 

Пусть таблица tblStudent включает следующие записи:

 

tblStudent

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

1023

Бобров А.А.

10000

 

1025

Мухина В.Н.

12000

 

1026

Лобов А.Г.

14000

Пусть пользователь отправил на выполнение следующую команду:

Update tblStudent Set Grant = 18000

Эта команда отличается от предыдущей тем, что в результате ее выполнения изменению подвергнутся все три записи таблицы tblStudent. Как же сработает триггер в этой ситуации?

Как уже говорилось ранее, триггер будет вызван отдельно для каждой записи. Пусть записи обрабатываются в порядке возрастания идентификаторов.

СУБД начнет обрабатывать первую запись с идентификатором 1023, прежде, чем внести изменения, СУБД вызовет триггер и заполнит переменные OLD и NEW:

OLD

 

StudentId

 

StudentName

 

Grant

 

 

 

 

 

 

 

 

1023

 

Бобров А.А.

 

10000

 

 

NEW

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

StudentId

 

StudentName

 

Grant

 

 

 

1023

 

Бобров А.А.

 

18000

 

 

 

 

 

 

 

 

 

 

 

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

13

ПетрГУ, кафедра прикладной математики и кибернетики

Триггер внесет изменения в переменную NEW, так как для этой записи ограничения предметной области не выполняются:

OLD

 

StudentId

StudentName

Grant

 

1023

Бобров А.А.

10000

NEW

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

1023

Бобров А.А.

10500

Затем СУБД внесет изменения в таблицу tblStudent. tblStudent

StudentId

StudentName

Grant

1023

Бобров А.А.

10500

1025

Мухина В.Н.

12000

1026

Лобов А.Г.

14000

Далее СУБД перейдет к обработке второй записи с идентификатором 1025, прежде, чем внести изменения, СУБД вызовет триггер и заполнит переменные OLD и NEW:

OLD

 

StudentId

StudentName

Grant

 

1025

Мухина В.Н.

12000

NEW

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

1025

Мухина В.Н.

18000

Триггер внесет изменения в переменную NEW, так как для этой записи ограничения предметной области не выполняются:

OLD

 

StudentId

StudentName

Grant

 

1025

Мухина В.Н.

12000

NEW

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

1025

Мухина В.Н.

12600

Затем СУБД внесет изменения в таблицу tblStudent. tblStudent

 

StudentId

StudentName

Grant

 

 

 

1023

Бобров А.А.

10500

 

 

 

1025

Мухина В.Н.

12600

 

 

 

1026

Лобов А.Г.

14000

 

 

 

 

 

 

 

 

 

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

14

ПетрГУ, кафедра прикладной математики и кибернетики

Далее СУБД перейдет к обработке третей записи с идентификатором 1026, прежде, чем внести изменения, СУБД вызовет триггер и заполнит переменные OLD и NEW:

OLD

 

StudentId

StudentName

Grant

 

1026

Лобов А.Г.

14000

NEW

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

1026

Лобов А.Г.

18000

Триггер внесет изменения в переменную NEW, так как для этой записи ограничения предметной области не выполняются:

OLD

 

StudentId

StudentName

Grant

 

1026

Лобов А.Г.

14000

NEW

 

 

 

 

 

 

 

 

 

 

 

StudentId

StudentName

Grant

 

 

1026

Лобов А.Г.

14700

 

Затем СУБД внесет изменения в таблицу tblStudent. tblStudent

StudentId

StudentName

Grant

1023

Бобров А.А.

10500

1025

Мухина В.Н.

12600

1026

Лобов А.Г.

14700

Таким образом, СУБД вызовет триггер 3 раза.

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

Update tblStudent Set Grant = 12000

То триггер будет вызван также 3 раза, но условие, которое проверяет триггер, будет верным только для одной записи и триггер запишет правильное значение в запись с идентификатором 1023, в остальные записи триггер не внесет исправлений и СУБД, запишет в них указанное пользователем значение 12000. Таблица tblStudent будет содержать следующие записи:

tblStudent

 

StudentId

 

StudentName

 

Grant

 

 

 

 

 

 

 

 

1023

 

Бобров А.А.

 

11025

 

 

 

1025

 

Мухина В.Н.

 

12000

 

 

 

1026

 

Лобов А.Г.

 

12000

 

 

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

15

ПетрГУ, кафедра прикладной математики и кибернетики

Пример 2

Ограничение предметной области: количество практик по дисциплине математического факультета должно превышать количество часов лекций.

Это условие будем проверять для операции добавления новых данных в таблицу tblSubject.

CREATE TRIGGER tgrNewSubjectInsert BEFORE INSERT

ON tblSubject BEGIN

DECLARE FName char(100);

SELECT FName= FacultyName FROM tblFaculty WHERE FacultyId=NEW.FacultyId;

IF (FName =’математический’) and (NEW.LecturesHour >= NEW.PracticeHour)

BEGIN

Print('На математическом факультете практик должно быть больше, чем лекций');

ROLLBACK TRANSACTION;

END END

До добавления новой записи в табицу tblSubject будет вызван триггер tgrNewSubjectInsert, который в таблице tblFaculty по идентификатору факультета узнает название факультета, и запишет его в переменную FName; далее триггер проверит условие, что факультет носит имя «математический» и количество часов лекций меньше или равно количеству часов практик, если условие будет верным, то триггер выведет сообщение об ошибке и выполнит откат транзакции, который приведет к отмене ввода новой записи.

Например, пусть таблица tblFaculty имеет следующие записи: tblFaculty

FacultyId

FacultyName

DeenName

FacultyRoomId

FacultyPhone

FacultyStudent

1

Физико-

Звонов А.П.

132

710945

568

 

технический

 

 

 

 

 

 

 

 

 

 

2

Математический

Кашин О.И.

243

713498

603

 

 

 

 

 

 

Если пользователь попытается выполнить следующую команду:

Insert into tblSubject(SubjectName, LecturesHour, PracticeHour, FacultyId) values(‘Информатика’, 30, 51, 2), values(‘Информатика’, 30, 20, 1)

Эта команда будет успешно выполнена, так как первая добавляемая запись вносит дисциплину «Информатика» для математического факультета с количеством практик 51, а количеством лекций – 30, т.е. ограничение предметной области не нарушается, а вторая запись добавляет предмет «Информатика» для физико-технического факультета, и хотя здесь количество часов практик не превосходит количество часов лекций, но предмет будет

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

16

ПетрГУ, кафедра прикладной математики и кибернетики

читаться не на математическом факультете, поэтому ограничение предметной области здесь то же не нарушается.

Если пользователь попытается выполнить команду:

Insert into tblSubject(SubjectName, LecturesHour, PracticeHour, FacultyId) values(‘Алгебра’, 30, 51, 2), values(‘Физика’, 30, 20, 2)

Эта команда не будет выполнена. В таблицу tblSubject не будет добавлена ни одна запись, хотя первая добавляемая запись удовлетворяет ограничениям предметной области, но так как она добавляется в таблицу в рамках одной команды (одной транзакции) с другой записью, которая не удовлетворяет ограничениям предметной области, то обе записи не будут добавлены в таблицу (будет вызван откат транзакции, выполнявшей команду Insert).

Пример 3

Ограничение предметной области: количество студентов в одной группе не должно превышать значение 25.

Это условие будем проверять для операции добавления новых данных в таблицу tblStudent.

CREATE TRIGGER tgrNewStudentInsert AFTER INSERT ON tblStudent

BEGIN

DECLARE idGroup int, GCount int;

SELECT GCount=count(*) FROM tblStudent WHERE GroupId=NEW.GroupId; IF (GCount >25)

BEGIN

Print ('В группе не может быть более 25 студентов'); ROLLBACK TRANSACTION;

END END

После добавления новых записей будет вызван триггер, который подсчитает количество студентов, которые учатся в той же группе, в которую зачислен студент, и запишет его в переменную GCount; далее триггер проверит условие, что количество студентов в группе не превосходит значения 25, если условие будет верным, то триггер вызовет исключительную ситуацию и откат транзакции, которые приведут к отмене ввода всех записей.

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

Пример 4

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

Таблица tblFaculty включает столбец с именем FacultyStudent, который должен содержать суммарное количество студентов, обучающихся на факультете. Каждый студент описывается

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

17

ПетрГУ, кафедра прикладной математики и кибернетики

записью в таблице tblStudent. Следовательно, данные в таблицах tblFaculty и tblStudent должны быть согласованы, т.е., если в таблице tblFaculty указано, что на математическом факультете обучается 214 студентов, то в таблице tblStudent должно быть ровно 214 записей с информацией о 214-ти студентах математического факультета, не считая записи для других факультетов. И если в таблицу tblStudent добавляется новый студент, или удаляется информация о студенте, то соответственно должно измениться значение в таблице tblFaculty. Для автоматического согласования данных в двух таблицах создадим два триггера для таблицы tblStudent.

CREATE TRIGGER tgrStudentInsert AFTER INSERT, UPDATE

ON tblStudent BEGIN

DECLARE idFaculty int, TotalSum int;

Select idFaculty=FacultyId From tblGroup Where GroupId=NEW.GroupId; EXECUTE prStudentsOfFaculty (idFaculty, TotalSum);

UPDATE tblFaculty SET FacultyStudent=TotalSum WHERE FacultyId=idFaculty;

END

CREATE TRIGGER tgrStudentDelete AFTER DELETE ON tblStudent

BEGIN

OPEN DelCursor;

DECLARE idFaculty int, TotalSum int;

Select idFaculty=FacultyId From tblGroup Where GroupId=OLD.GroupId; EXECUTE prStudentsOfFaculty (idFaculty, TotalSum);

UPDATE tblFaculty SET FacultyStudent=TotalSum WHERE FacultyId=idFaculty;

END

Триггер tgrStudentInsert вызывается для операций Insert и Update, а триггер tgrStudentDelete – для операции Delete. Работают они одинаково, единственное отличие заключается в том, что при добавлении записей используется переменная NEW, а при удалении – OLD, поэтому триггеры отличаются только формулировкой запроса для получения идентификатора факультета.

Для каждой изменяемой (добавляемой/удаляемой) записи триггер по идентификатору группы находит идентификатор факультета, на котором учится студент, вызывает процедуру, которая подсчитывает общее количество студентов на факультете, и вносит правильное значение в соответствующую строку таблицы tblFaculty.

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

18

ПетрГУ, кафедра прикладной математики и кибернетики

Пример 5

Генерация уникального идентификатора аудитории.

При добавлении новых данных в таблицу tblRoom необходимо указать значение идентификатора записи. Так как эти значения абсолютно условны, т.е. их не существует в предметной области, они были введены в структуру таблицы в качестве искусственного ключа, то не стоит утруждать пользователя в выдумывании этих значений. Эти значения должны генерироваться автоматически и быть уникальными. Для генерации нового значения воспользуемся механизмом триггера и будем использовать простейший алгоритм, заключающийся в нахождении максимального идентификатора для уже имеющихся в таблице tblRoom записей, и увеличении этого значения на единицу, таким образом, получим новое уникальное значение.

CREATE TRIGGER tgrRoomInsert

BEFORE INSERT ON tblRoom

BEGIN

DECLARE idRoom int;

SELECT idRoom = max(RoomId) from tblRoom;

SET idRoom=idRoom+1;

NEW.RoomId=idRoom;

END

Пусть таблица tblRoom содержит следующие записи: tblRoom

RoomId

RoomNumber

PlaceCount

SmartBoard

RoomFloor

 

 

 

 

 

1

105

27

1

1

 

 

 

 

 

3

201

14

0

2

 

 

 

 

 

7

203

30

0

2

 

 

 

 

 

Если пользователь попытается выполнить следующую команду

insert into tblRoom(RoomNumber, RoomFloor) values(‘327a’, 3), (‘403’, 4)

таблица tblRoom станет такой: tblRoom

RoomId

RoomNumber

PlaceCount

SmartBoard

RoomFloor

 

 

 

 

 

1

105

27

1

1

 

 

 

 

 

3

201

14

0

2

 

 

 

 

 

7

203

30

0

2

 

 

 

 

 

8

327a

Null

Null

3

 

 

 

 

 

9

403

Null

Null

4

 

 

 

 

 

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

19

ПетрГУ, кафедра прикладной математики и кибернетики

Для двух добавленных записей будут сгенерированы значения поля RoomId: 8 и 9 соответственно. Так как пользователь не указал значения для полей PlaceCount и SmartBoard, то эти поля получили значения NULL.

Конспект лекций по дисциплине «Базы данных» (Процедуры и триггеры)

20