-
Notifications
You must be signed in to change notification settings - Fork 0
lab_12 #23
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
1
commit into
main
Choose a base branch
from
lab_12
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_12 #23
Changes from all commits
Commits
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,293 @@ | ||
| --Лабораторная работа 12. Создание процедур и функций на языке plpgsql. Обработка исключений | ||
|
|
||
| -- 1. Создайте функцию, которая будет принимать массив символьных значений и шаблон | ||
| -- (например, шаблон телефона). Функция должна возвращать False если хотя бы значение одного | ||
| -- элемента массива не соответствует шаблону. Иначе функция должна вернуть – True. | ||
| -- Функция должна работать на произвольном количестве элементов массива с произвольным шаблоном. | ||
|
|
||
| create function schema2.check_array( | ||
| values_arr text[], | ||
| pattern text | ||
| ) | ||
| returns boolean | ||
| language plpgsql | ||
| as $$ | ||
| declare | ||
| v text; | ||
| begin | ||
| if values_arr is null or pattern is null then | ||
| return false; | ||
| end if; | ||
|
|
||
| foreach v in array values_arr loop | ||
| if v !~ pattern then | ||
| return false; | ||
| end if; | ||
| end loop; | ||
|
|
||
| return true; | ||
| end; | ||
| $$; | ||
|
|
||
| select schema2.check_array( | ||
| array['123','456'], '^[0-9]{3}$' | ||
| )::text as result; | ||
|
|
||
| -- 2. Создайте процедуру. Процедура должна получать идентификатор | ||
| -- сотрудника и его телефон. | ||
|
|
||
| create domain public.phone as text | ||
| check ( | ||
| value ~ '^8\([0-9]{3}\)[0-9]{3}-[0-9]{4}$' | ||
| ); | ||
| --(не смог найти созданный ранее) | ||
|
|
||
| create or replace procedure schema2.add_employee( | ||
| p_employee_id numeric, | ||
| p_phone text | ||
| ) | ||
| language plpgsql | ||
| as $$ | ||
| declare | ||
| phones text[]; | ||
| digits text; | ||
| begin | ||
| if p_phone is null or length(trim(p_phone)) = 0 then | ||
| raise exception 'поле "телефон" пустое'; | ||
| end if; | ||
|
|
||
| select e.phone_number | ||
| into phones | ||
| from schema1.employees e | ||
| where e.employee_id = p_employee_id; | ||
|
|
||
| if not found then | ||
| raise exception 'сотрудник с id % не найден', p_employee_id; | ||
| end if; | ||
|
|
||
| phones := coalesce(phones, array[]::text[]); | ||
|
|
||
| digits := regexp_replace(p_phone, '\D', '', 'g'); | ||
|
|
||
| if length(digits) = 11 and left(digits, 1) = '8' then | ||
| digits := '7' || substr(digits, 2); | ||
| end if; | ||
|
|
||
| if digits !~ '^7[0-9]{10}$' then | ||
| raise exception 'неверный формат телефона: %', p_phone; | ||
| end if; | ||
|
|
||
| if digits = any(phones) then | ||
| raise info 'телефон % уже существует у сотрудника %', digits, p_employee_id; | ||
| return; | ||
| end if; | ||
|
|
||
| update schema1.employees | ||
| set phone_number = array_append(phones, digits) | ||
| where employee_id = p_employee_id; | ||
|
|
||
| raise info 'номер % добавлен сотруднику % (из "%")', digits, p_employee_id, p_phone; | ||
| end; | ||
| $$; | ||
|
|
||
|
|
||
| call schema2.add_employee(13, '+7-999-123-45-67'); | ||
|
|
||
| select employee_id, phone_number | ||
| from schema1.employees | ||
| where employee_id = 13; | ||
| -- номер добавлен успешно | ||
|
|
||
| call schema2.add_employee(13, '8(999)123-4567'); | ||
| -- номер существует | ||
|
|
||
| call schema2.add_employee(1000, '8(999)123-4567'); | ||
| -- такого сотрудника нет | ||
|
|
||
|
|
||
|
|
||
| -- 3. Создайте процедуру для добавления нового департамента. | ||
| create procedure schema2.add_department( | ||
| department_id numeric, | ||
| department_name text, | ||
| manager_id numeric, | ||
| location_id numeric default null | ||
| ) | ||
| language plpgsql | ||
| as $$ | ||
| begin | ||
| if department_id is null then | ||
| raise exception 'не заполнено обязательное поле department_id'; | ||
| end if; | ||
|
|
||
| if department_name is null or length(trim(department_name)) = 0 then | ||
| raise exception 'не заполнено обязательное поле department_name'; | ||
| end if; | ||
|
|
||
| if manager_id is null then | ||
| raise exception 'не заполнено обязательное поле manager_id'; | ||
| end if; | ||
|
|
||
| begin | ||
| insert into schema1.departments(department_id, department_name, manager_id, location_id) | ||
| values (department_id, department_name, manager_id, location_id); | ||
|
|
||
| raise info 'департамент "%" (id=%) успешно добавлен', department_name, department_id; | ||
|
|
||
| exception | ||
| when unique_violation then | ||
| raise exception 'department_id или другое уникальное поле уже существует'; | ||
| when foreign_key_violation then | ||
| raise exception 'нарушение внешнего ключа (manager_id/location_id)'; | ||
| when not_null_violation then | ||
| raise exception 'не заполнено обязательное поле (NOT NULL)'; | ||
| when check_violation then | ||
| raise exception 'значение не прошло проверку (CHECK)'; | ||
| when others then | ||
| raise exception 'ошибка при добавлении департамента: %', sqlerrm; | ||
| end; | ||
| end; | ||
| $$; | ||
|
|
||
| call schema2.add_department(5001, 'Dept_1', 100); | ||
| -- добавлено | ||
|
|
||
| call schema2.add_department(null, 'Dept_2', 100); | ||
| -- не заполнено обязательное поле | ||
|
|
||
| call schema2.add_department(9300, 'Dept_3', 9999999, null); | ||
| -- ошибка при добавлении департамента | ||
|
|
||
|
|
||
|
|
||
| -- 4 | ||
| create procedure schema2.add_address( | ||
| p_full_address text | ||
| ) | ||
| language plpgsql | ||
| as $$ | ||
| declare | ||
| parts text[]; | ||
| v_location_id integer; | ||
| v_street text; | ||
| v_postal text; | ||
| v_city text; | ||
| v_country_id integer; | ||
| begin | ||
| if p_full_address is null or length(trim(p_full_address)) = 0 then | ||
| raise exception 'строка адреса пустая'; | ||
| end if; | ||
|
|
||
| parts := string_to_array(p_full_address, ';'); | ||
|
|
||
| if array_length(parts, 1) <> 4 then | ||
| raise exception 'формат "street_address; postal_code; city; country_id"'; | ||
| end if; | ||
|
|
||
| v_street := trim(parts[1]); | ||
| v_postal := nullif(trim(parts[2]), ''); | ||
| v_city := trim(parts[3]); | ||
|
|
||
| begin | ||
| v_country_id := trim(parts[4])::integer; | ||
| exception | ||
| when invalid_text_representation then | ||
| raise exception 'country_id должен быть числом'; | ||
| end; | ||
|
|
||
| if v_street is null or v_city is null | ||
| or length(v_street)=0 or length(v_city)=0 then | ||
| raise exception 'обязательные поля street_address и city'; | ||
| end if; | ||
|
|
||
| if exists ( | ||
| select 1 | ||
| from schema1.locations a | ||
| where a.street_address = v_street | ||
| and coalesce(a.postal_code,'') = coalesce(v_postal,'') | ||
| and a.city = v_city | ||
| and a.country_id = v_country_id | ||
| ) then | ||
| raise exception 'такой адрес уже существует'; | ||
| end if; | ||
|
|
||
| select coalesce(max(location_id), 0) + 1 | ||
| into v_location_id | ||
| from schema1.locations; | ||
|
|
||
| insert into schema1.locations(location_id, street_address, postal_code, city, country_id) | ||
| values (v_location_id, v_street, v_postal, v_city, v_country_id); | ||
|
|
||
| raise info 'Адрес добавлен. location_id=%', v_location_id; | ||
| end; | ||
| $$; | ||
|
|
||
| call schema2.add_address('Pervomayskaya 10; 1010; Saint-P; 1'); | ||
| call schema2.add_address('Lomonosova 15; 1010; Москва; 1'); | ||
|
|
||
| select * | ||
| from schema1.locations | ||
| where postal_code = '1010'; | ||
| -- адреса добавлены | ||
|
|
||
|
|
||
|
|
||
| -- 5. Создайте функцию. Функция должна принимать название города и | ||
| -- возвращать список подразделений, расположенных в указанном городе, | ||
| -- и количество сотрудников в этих подразделениях в виде json документ | ||
| -- следующего вида: {город: название_города, подразделения: | ||
| -- [{название:название_подразделения, сотрудники:[список сотрудников]},{}…]}. | ||
| -- Если в указанном городе нет подразделений функция должна возвращать | ||
| -- информационное сообщение | ||
|
|
||
| create function schema2.get_departments(p_city text) | ||
| returns json | ||
| language plpgsql | ||
| as $$ | ||
| declare | ||
| dept_cnt int; | ||
| result json; | ||
| begin | ||
| if p_city is null or length(trim(p_city)) = 0 then | ||
| return json_build_object('message', 'Город не задан'); | ||
| end if; | ||
|
|
||
| select count(*) | ||
| into dept_cnt | ||
| from schema1.departments d | ||
| join schema1.locations a | ||
| on a.location_id = d.location_id | ||
| where lower(a.city) = lower(trim(p_city)); | ||
|
|
||
| if dept_cnt = 0 then | ||
| return json_build_object('message', format('В городе "%s" нет подразделений', trim(p_city))); | ||
| end if; | ||
|
|
||
| select json_build_object( | ||
| 'город', trim(p_city), | ||
| 'подразделения', | ||
| json_agg( | ||
| json_build_object( | ||
| 'название', d.department_name, | ||
| 'сотрудники', | ||
| coalesce( | ||
| (select json_agg(e.last_name || ' ' || e.first_name order by e.last_name, e.first_name) | ||
| from schema1.employees e | ||
| where e.department_id = d.department_id), | ||
| '[]'::json | ||
| ) | ||
| ) | ||
| order by d.department_name | ||
| ) | ||
| ) | ||
| into result | ||
| from schema1.departments d | ||
| join schema1.locations a | ||
| on a.location_id = d.location_id | ||
| where lower(a.city) = lower(trim(p_city)); | ||
|
|
||
| return result; | ||
| end; | ||
| $$; | ||
|
|
||
| select schema2.get_departments('Paris'); | ||
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.
Это конфликт с лабой 11 или 13 вроде бы.