
Лабораторная работа №2 БД-1
.pdfМИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
ИНСТИТУТ НЕПРЕРЫВНОГО И ДИСТАНЦИОННОГО ОБРАЗОВАНИЯ
КАФЕДРА ПРИКЛАДНОЙ ИНФОРМАТИКИ
ОЦЕНКА |
|
|
ПРЕПОДАВАТЕЛЬ |
|
|
канд. техн. наук, доцент |
подпись, дата |
Е. Л. Турнецкая |
должность, уч. степень, звание |
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ
Лабораторная работа №2. Программная реализация триггеров
по дисциплине: Базы данных
РАБОТУ ВЫПОЛНИЛ |
|
|
|
|
|
СТУДЕНТ гр. № |
Z1411 |
|
|
Я. Н. Тюттерин |
|
|
номер группы |
|
подпись, дата |
|
инициалы, фамилия |
Студенческий билет № |
2022 / 4886 |
|
|
|
|
|
|
|
|
|
Санкт-Петербург 2024

Лабораторная работа № 2. Программная реализация триггеров
Цель работы: получение практических навыков по программной реализации триггеров на сервере PostgreSQL.
Для начала поставим цель. Предположим, что в БД нет возможности производить удаление связанных записей при удалении родительской. То есть отсутствует функционал вида REFERENCES ON DELETE CASCADE. В связи с этим требуется необходим триггер, который будет удалять записи из связующей таблицы, иначе БД не позволит удалить записи из родительской таблицы.
Например, у нас есть таблицы работников и их достижений. Связаны они связью многие ко многих через таблицу achievement_worker.
Для начала потребуется функция, которая будет вызываться из триггера при удалении записи из таблицы с достижениями. Ее листинг представлен ниже.
CREATE OR REPLACE FUNCTION delete_from_achievement_worker() RETURNS TRIGGER
AS $$
begin
delete from achievement_worker where achievement_id = old.id;
RETURN old;
END;
$$ LANGUAGE plpgsql;
Далее необходимо создать триггер, который при удалении из таблицы достижений, будет вызываться непосредственно перед удалением записи. Это поведение указывается с помощью BEFORE. В результате получим:
CREATE TRIGGER before_delete_achievements
BEFORE DELETE ON achievements
FOR EACH ROW
EXECUTE FUNCTION delete_from_achievement_worker();
Содержимое связующей таблицы достижений и работников представлено на рисунке 1.

Рисунок 1 - Содержимое связующей таблицы
Выполним запрос delete from achievements where id = 6; В результате получили результат, представленный на рисунке 2.
Рисунок 2 - Результат выполнения запроса с исполнением триггера на удаление
Теперь начнем работу над INSERT-триггером. Например, нам потребовалось сделать так, чтобы при добавлении нового работнику в нашу систему и, если его возраст меньше 25, то ему сразу же добавляется достижение - “Молодой специалист”.
Для начала необходимо завести функцию, которая будет вызываться в триггере. Содержимое таблицы с достижениями представлено на рисунке 3.

Рисунок 3 - Содержимое таблицы достижений
Листинг функции представлен ниже:
CREATE OR REPLACE FUNCTION add_achievent_for_young_specialist() RETURNS TRIGGER
AS $$
begin
insert into achievement_worker(achievement_id, worker_id) values (7, new.id);
RETURN old;
END;
$$ LANGUAGE plpgsql;
Теперь создадим триггер, который будет вызывать эту функцию. Используется AFTER, так как на этапе вставки в связующую таблицу - значение идентификатора создаваемое пользователя уже должно быть известно. Листинг представлен ниже:
CREATE TRIGGER trigger_add_achievent_for_young_specialist after insert ON workers
for each row
when ((DATE_PART('year', CURRENT_DATE) - DATE_PART('year', new.date_of_birth)) <= 25)
EXECUTE FUNCTION add_achievent_for_young_specialist();
Содержимое связующей таблицы до вставки нового работника представлено на рисунке 4.

Рисунок 4 - Содержимое связующей таблицы до вставки
Выполним запрос INSERT INTO workers(first_name, last_name, patronymic, gender, salary,
date_of_birth) VALUES ('Tyutterin', 'Yakov', 'Nikolaevich', 'M', 100000, '2001-08-06');. Содержимое связующей таблицы после вставки представлено на рисунке 5.
Рисунок 5 - Содержимое связующей таблицы после вставки
При попытке добавить работника с большим возрастом - достижение не будет добавлено. Выполним INSERT INTO workers(first_name, last_name, patronymic, gender, salary,
date_of_birth) VALUES ('Zotov', 'Mikhail', 'Urievich', 'M', 110000, '1978-01-20');. Результаты
представлены на рисунках 6-7.

Рисунок 6 - Вставка новой записи
Рисунок 7 - Содержимое связующей таблицы

Поступила еще одна задача и теперь, при увольнении работника, мы не должны удалять его из таблицы БД, а должны обновить соответствующий флаг и удалить всю информацию о его достижениях и позициях.
Для начала необходимо добавить эту колонку в таблицу работников. Для этого необходимо выполнить:
alter table workers add column active boolean default true;
alter table workers alter column active set not null;
Теперь можно приступить к написанию функции для триггера. Ее листинг представлен ниже:
CREATE OR REPLACE FUNCTION delete_achievents_and_positions_on_deactivation_worker()
RETURNS TRIGGER AS $$ begin
delete from achievement_worker where worker_id = old.id; delete from position_worker where worker_id = old.id;
RETURN old;
END;
$$ LANGUAGE plpgsql;
Листинг создания триггера представлен ниже:
CREATE TRIGGER trigger_on_deactivation_worker
before update ON workers
for each row
when (old.active != new.active and new.active = false)
EXECUTE FUNCTION delete_achievents_and_positions_on_deactivation_worker();
Рисунок 8 - Содержимое связующей таблицы достижений

Рисунок 9 - Содержимое связующей таблицы позиций
Выполним запрос для деактивации работника с идентификатором 3, update workers set active = false where id = 3;. Результаты выполнения триггера представлены на рисунках
10-11.
Рисунок 10 - Содержимое после выполнения триггера

Рисунок 11 - Содержимое после выполнения триггера
Вывод
В результате проделанной работы были изучены различные варианты создания триггеров. Разобраны и опробованы варианты BEFORE и AFTER для исполнения триггера до и после выполнения запроса.
Список использованных источников
1)Методические указания по выполнению лабораторной работы: https://pro.guap.ru/inside/student/tasks/314b0b1fbbcd44ddc3b8eb6f373fd950/download
2)Документаци по триггерам в PostgreSQL: https://www.postgresql.org/docs/current/sql-createtrigger.html
3)Документация по работе с функциями в PostgreSQL: https://www.postgresql.org/docs/current/sql-createfunction.html
4)Документация по PostgreSQL: https://www.postgresql.org/docs/current/ddl-alter.html