-
Notifications
You must be signed in to change notification settings - Fork 0
lab_13 #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
plidan123
wants to merge
2
commits into
main
Choose a base branch
from
lab_13
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
lab_13 #24
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,332 @@ | ||
| -- Лабораторная 13. Создание триггеров | ||
|
|
||
| -- 1. Реализуйте следующее решение: | ||
| -- a. Создайте триггерную функцию check_salary, которая вызывает | ||
| -- исключение, если новая зарплата сотрудника больше старой на 100%. | ||
| create or replace function schema1.check_salary() | ||
| returns trigger | ||
| language plpgsql | ||
| as $$ | ||
| begin | ||
| if new.salary is distinct from old.salary then | ||
| if new.salary > old.salary * 2 then | ||
| raise exception | ||
| 'зарплата увеличена более чем на 100%% (%s, %s, employee_id=%s)', | ||
| old.salary, new.salary, old.employee_id; | ||
| end if; | ||
| end if; | ||
|
|
||
| return new; | ||
| end; | ||
| $$; | ||
|
|
||
| -- b. Создайте триггер BEFORE UPDATE - before_update_salary, который | ||
| -- вызывает функцию check_salary перед обновлением значения в столбце salary для каждой записи. | ||
| create trigger before_update_salary | ||
| before update of salary on schema1.employees | ||
| for each row | ||
| execute function schema1.check_salary(); | ||
|
|
||
| -- c. Обновите зарплату сотрудника с идентификатором 1 и убедитесь, | ||
| -- что триггер сработал и вернул соответствующее сообщение | ||
| update schema1.employees | ||
| set salary = salary * 3 | ||
| where employee_id = 1; | ||
| -- сработал триггер и изменение не применилось, так как вызвался raise exception | ||
|
|
||
| -- d. Переименуйте before_update_salary триггер в salary_before_update | ||
| alter trigger before_update_salary | ||
| on schema1.employees | ||
| rename to salary_before_update; | ||
|
|
||
| -- e. Отключите триггер salary_before_update. Обновите зарплату сотрудника | ||
| -- с идентификатором 2 и убедитесь, что триггер не сработал. | ||
| alter table schema1.employees | ||
| disable trigger salary_before_update; | ||
|
|
||
| update schema1.employees | ||
| set salary = salary * 3 | ||
| where employee_id = 2; | ||
| -- изменилась | ||
|
|
||
| -- f. Измените имя функции check_salary на validate_salary. | ||
| alter function schema1.check_salary() | ||
| rename to validate_salary; | ||
|
|
||
| -- g. Измените «привязку» триггера к триггерной функции validate_salary | ||
| drop trigger salary_before_update on schema1.employees; | ||
|
|
||
| create trigger salary_before_update | ||
| before update of salary on schema1.employees | ||
| for each row | ||
| execute function schema1.validate_salary(); | ||
|
|
||
| -- h. Выполните проверку | ||
| update schema1.employees | ||
| set salary = salary * 3 | ||
| where employee_id = 1; | ||
| -- триггер сработал | ||
|
|
||
| -- 2. Добавьте в таблицу employees 2 новых столбца: | ||
| -- a. login – для сохранения учетной записи сотрудника | ||
| -- b. password– для сохранения пароля сотрудника | ||
|
|
||
| alter table schema1.employees | ||
| add column login character varying, | ||
| add column password character varying; | ||
|
|
||
| -- 3. Создайте триггер, который будет срабатывать при добавлении или изменении | ||
| -- записей о сотрудниках: | ||
| -- a. Login и password не должны быть одинаковыми, при этом их длина должна быть | ||
| -- больше или равна 8 символов. Поля не должны содержать NULL значения. | ||
| -- b. В случае нарушения данных условий должно генерироваться пользовательское | ||
| -- исключение, предоставляющее информацию о нарушении | ||
|
|
||
| create function schema1.validate_employee() | ||
| returns trigger | ||
| language plpgsql | ||
| as $$ | ||
| begin | ||
| if new.login is null or new.password is null then | ||
| raise exception | ||
| 'поля login и password не должны быть null'; | ||
| end if; | ||
|
|
||
| if length(new.login) < 8 or length(new.password) < 8 then | ||
| raise exception | ||
| 'длина login и password должна быть не менее 8 символов'; | ||
| end if; | ||
|
|
||
| if new.login = new.password then | ||
| raise exception | ||
| 'login и password не должны совпадать'; | ||
| end if; | ||
|
|
||
| return new; | ||
| end; | ||
| $$; | ||
| create trigger validate_employee_data | ||
| before insert or update of login, password | ||
| on schema1.employees | ||
| for each row | ||
| execute function schema1.validate_employee(); | ||
|
|
||
| -- c. Протестируйте ваш триггер | ||
| update schema1.employees | ||
| set login = null | ||
| where employee_id = 1; | ||
|
|
||
| update schema1.employees | ||
| set login = '123', | ||
| password = '125678932' | ||
| where employee_id = 1; | ||
|
|
||
| update schema1.employees | ||
| set login = '12345678', | ||
| password = '12345678' | ||
| where employee_id = 1; | ||
|
|
||
| update schema1.employees | ||
| set login = 'user_login', | ||
| password = 'secure_pwd' | ||
| where employee_id = 1; | ||
|
|
||
| -- все работает | ||
|
|
||
| -- d. Удалите созданный триггер | ||
| drop trigger validate_employee_data on schema1.employees; | ||
|
|
||
| -- 4. Необходимо реализовать процедурную поддержку процесса карьерных | ||
| -- перемещений сотрудников - таблица job_history в схеме schema1 | ||
| -- a. Таблица employees должна содержать только актуальную информацию о активных сотрудниках | ||
| -- b. Таблица job_history должна содержать информацию о всех «изменениях» сотрудника: прием, | ||
| -- увольнение, изменение должности, изменение отдела, изменение заработной платы. | ||
| -- c. Тип изменения должен сохранятся в столбце type_operation в таблице job_history | ||
|
|
||
| ALTER TABLE schema1.job_history | ||
| ALTER COLUMN end_date DROP NOT NULL; | ||
| ALTER TABLE schema1.job_history | ||
| ADD COLUMN location_id numeric(4,0), | ||
| ADD COLUMN type_operation text; | ||
|
|
||
|
|
||
| create or replace function schema1.employee_changes() | ||
| returns trigger | ||
| language plpgsql | ||
| as $$ | ||
| declare | ||
| v_employee_id numeric(6,0); | ||
| v_job_id varchar(10); | ||
| v_department_id numeric(4,0); | ||
| v_salary numeric(10,2); | ||
| v_location_id numeric(4,0); | ||
| v_start_date date; | ||
| v_end_date date; | ||
| v_op text; | ||
| begin | ||
| if lower(tg_op) = 'insert' then | ||
| v_employee_id := new.employee_id; | ||
| v_job_id := new.job_id; | ||
| v_department_id := new.department_id; | ||
| v_salary := new.salary; | ||
| v_start_date := new.hire_date; | ||
| v_end_date := null; | ||
| v_op := 'hire'; | ||
|
|
||
| elsif lower(tg_op) = 'update' then | ||
| if new.job_id is distinct from old.job_id then | ||
| v_op := 'job_change'; | ||
| elsif new.department_id is distinct from old.department_id then | ||
| v_op := 'dept_change'; | ||
| elsif new.salary is distinct from old.salary then | ||
| v_op := 'salary_change'; | ||
| else | ||
| return new; | ||
| end if; | ||
|
|
||
| v_employee_id := new.employee_id; | ||
| v_job_id := new.job_id; | ||
| v_department_id := new.department_id; | ||
| v_salary := new.salary; | ||
| v_start_date := current_date; | ||
| v_end_date := null; | ||
|
|
||
| update schema1.job_history | ||
| set end_date = current_date | ||
| where employee_id = old.employee_id | ||
| and end_date is null; | ||
|
|
||
| elsif lower(tg_op) = 'delete' then | ||
| v_employee_id := old.employee_id; | ||
| v_job_id := old.job_id; | ||
| v_department_id := old.department_id; | ||
| v_salary := old.salary; | ||
| v_start_date := current_date; | ||
| v_end_date := current_date; | ||
| v_op := 'fire'; | ||
|
|
||
| update schema1.job_history | ||
| set end_date = current_date | ||
| where employee_id = old.employee_id | ||
| and end_date is null; | ||
|
|
||
| else | ||
| return null; | ||
| end if; | ||
|
|
||
| select d.location_id | ||
| into v_location_id | ||
| from schema1.departments d | ||
| where d.department_id = v_department_id; | ||
|
|
||
| insert into schema1.job_history ( | ||
| employee_id, start_date, end_date, | ||
| job_id, department_id, salary, | ||
| location_id, type_operation | ||
| ) | ||
| values ( | ||
| v_employee_id, v_start_date, v_end_date, | ||
| v_job_id, v_department_id, v_salary, | ||
| v_location_id, v_op | ||
| ); | ||
|
|
||
| if lower(tg_op) = 'delete' then | ||
| return old; | ||
| end if; | ||
|
|
||
| return new; | ||
| end; | ||
| $$; | ||
|
|
||
| drop trigger if exists employee_history on schema1.employees; | ||
|
|
||
|
|
||
| create trigger employee_history | ||
| after insert or update or delete | ||
| on schema1.employees | ||
| for each row | ||
| execute function schema1.employee_changes(); | ||
|
|
||
| select count(*) as before_cnt | ||
| from schema1.job_history | ||
| where employee_id = 1; | ||
|
|
||
| -- проверили кол-во строк в истории | ||
|
|
||
| update schema1.employees | ||
| set salary = salary + 1 | ||
| where employee_id = 1; | ||
|
|
||
| -- сделали апдейт | ||
|
|
||
| select count(*) as after_cnt | ||
| from schema1.job_history | ||
| where employee_id = 1; | ||
|
|
||
| -- должно стать на 1 запись в истории больше | ||
|
|
||
| select * | ||
| from schema1.job_history | ||
| where employee_id = 1; | ||
|
|
||
| -- проверили запись | ||
|
|
||
| -- все работает | ||
|
|
||
|
|
||
| -- 5. Необходимо реализовать процедурную поддержку для проверки номеров телефона | ||
| -- сотрудников на соответствие заданному шаблону. Проверка должна осуществляться как при | ||
| -- вставке новых записей о сотрудниках, так и при изменении существующих. | ||
| create function schema1.validate_phone_array() | ||
| returns trigger | ||
| language plpgsql | ||
| as $$ | ||
| declare | ||
| ph phone; | ||
| begin | ||
| if new.phone_number is null or cardinality(new.phone_number) = 0 then | ||
| raise exception 'номер не должен быть null или пустым'; | ||
| end if; | ||
|
|
||
| foreach ph in array new.phone_number loop | ||
| if ph is null then | ||
| raise exception 'номер не должен содержать null значения'; | ||
| end if; | ||
| end loop; | ||
|
|
||
| if (select count(*) from unnest(new.phone_number) x) <> | ||
| (select count(distinct x) from unnest(new.phone_number) x) then | ||
| raise exception 'номер не должен содержать повторяющиеся номера'; | ||
| end if; | ||
|
|
||
| return new; | ||
| end; | ||
| $$; | ||
|
|
||
| create trigger validate_phone_number | ||
| before insert or update of phone_number | ||
| on schema1.employees | ||
| for each row | ||
| execute function schema1.validate_phone_array(); | ||
|
|
||
|
|
||
| update schema1.employees | ||
| set phone_number = '{}'::phone[] | ||
| where employee_id = 1; | ||
|
|
||
| update schema1.employees | ||
| set phone_number = array['8(900)000-4432','8(900)000-4432']::phone[] | ||
| where employee_id = 1; | ||
|
|
||
| update schema1.employees | ||
| set phone_number = array[null]::phone[] | ||
| where employee_id = 1; | ||
|
|
||
| update schema1.employees | ||
| set phone_number = array['8(950)111-2357','8(988)467-7000']::phone[] | ||
| where employee_id = 1; | ||
|
|
||
| select * from schema1.employees | ||
| where employee_id = 1; | ||
|
|
||
| -- все работает! | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.