С Новым годом! Форум программистов, компьютерный форум, киберфорум
PostgreSQL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
14 / 13 / 1
Регистрация: 17.04.2023
Сообщений: 107

Реализация хранимой процедуры

17.04.2023, 11:01. Показов 1361. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Недавно начал изучать sql. Имеется следующая таблица:

iddepartament_idnamechief_idsalary
11Технолог цеха545 000,00
21Механик цеха550 000,00
31Начальник цеха555 000,00
41Инженер ППР535 000,00
52Инженер 1535 000,00
62Инженер 2540 000,00
72Инженер 3545 000,00
83Бухгалтер 1640 000,00
93Бухгалтер 2650 000,00
103Главный бухгалтер6210 000,00
114Специалист 1730 000,00
124Специалист 2740 000,00
134Специалист 3750 000,00
145Директор 1null100 000,00
156Директор 2null200 000,00
167Директор 3null300 000,00

Была поставлена задача реализовать следующую процедуру:
1. На входе выбрать id отдела и процент повышения заработной платы (percent).
2. После повышения заработной платы произвести сравнение заработной платы выбранного отдела подчиненных работников с заработной платой соответствующего директора.
3. Если у директора зарплата оказалась ниже, чем у какого-либо подчиненного, то директору необходимо увеличить зарплату до зарплаты такого подчиненного.
4. После всего это вывести результаты, с зарплатами до и после повышения, процентом повышения зарплаты, id отделов и наименованием должностей.
5. Я смог самостоятельно реализовать только часть функционала (без сравнения заработных плат и их обновления в случае необходимости):
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CREATE OR REPLACE FUNCTION UPDATESALARYFORDEPARTMENT(IN INTEGER, IN REAL) 
RETURNS TABLE 
(
"Departament_ID" INTEGER, 
"Должность" VARCHAR, 
"Должность руководителя" VARCHAR, 
"chief_id" INTEGER, "Зарплата руководителя" money, 
"Зарплата подчин. до индекс." money, 
"Зарплата подчин. после индекс." money, 
"Процент индексации зарплаты" REAL)
AS 
$$
BEGIN RETURN query
SELECT a.Departament_ID, 
a.Name AS "Должность",
b.Name AS "Должность руководителя", 
a.chief_id, 
b.Salary AS "Зарплата руководителя", 
a.Salary AS "Зарплата подчин. до индекс.", 
(a.Salary*$2/100)+a.Salary AS "Зарплата подчин. после индекс.", 
$2 AS "Процент индексации зарплаты"
FROM Employee a
JOIN employee b ON b.departament_id = a.chief_id
WHERE a.Departament_ID = $1;
END;
$$
LANGUAGE plpgsql;
6. Собственно вопрос, как реализовать вывод данных после сравнения зарплаты и при необходимости, её обновления у директоров. С помощью гугла попробовал реализовать таким образом:
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
CREATE OR REPLACE FUNCTION UPDATESALARYFORDEPARTMENT(IN INTEGER, IN REAL) 
RETURNS TABLE 
(
"Departament_ID" INTEGER, 
"Должность" VARCHAR, 
"Должность руководителя" VARCHAR, 
"chiefid" INTEGER, 
"Зарплата руководителя" money,
"Зарплата подчин. до индекс." money, 
"Зарплата подчин. после индекс." money, 
"Процент индексации зарплаты" REAL)
AS 
$$
BEGIN RETURN query
WITH sup AS 
(
SELECT a.Departament_ID, 
a.Name AS "Должность",
b.Name AS "Должность руководителя", 
a.chief_id AS chiefid, 
b.Salary AS "Зарплата руководителя", 
a.Salary AS "Зарплата подчин. до индекс.", 
(a.Salary*$2/100)+a.Salary AS "Зарплата подчин. после индекс.", 
$2 AS "Процент индексации зарплаты"
FROM Employee a
JOIN employee b ON b.departament_id = a.chief_id
WHERE a.Departament_ID = $1)
UPDATE Employee 
SET Salary=sup."Зарплата подчин. после индекс."
FROM sup 
WHERE sup."Зарплата руководителя"<sup."Зарплата подчин. после индекс." AND chief_id IS NULL;
END;
$$
LANGUAGE plpgsql;
Но выдается ошибка "запрос UPDATE не возвращает кортежи". Буду рад помощи и разъяснением.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.04.2023, 11:01
Ответы с готовыми решениями:

Код хранимой процедуры
Ребят, ничего толком не знаю о PostgreSQL. Но есть БД, в которой нужно создать хранимую процедуру, для последующей работы в C#. САМА...

Написание хранимой процедуры
Недавно начал работать с базами данных, наткнулся на такое задание, написать хранимую процедуру, которая будет отправлять сообщения по...

Ограничение хранимой процедуры 100 параметров
Добрый день. Мы не можем создать хранимую процедуру в которой больше 100 параметров. В документации написано. Параметр...

8
55 / 50 / 5
Регистрация: 30.06.2022
Сообщений: 251
17.04.2023, 13:46
искать в доке слово RETURING
+
переписать запрос UPDATE с ним
0
14 / 13 / 1
Регистрация: 17.04.2023
Сообщений: 107
02.05.2023, 07:35  [ТС]
Вопрос все еще в силе. Переделал как подсказал oktogen с RETURING. Не работает. Просьба по возможности максимально подробнее разъяснить, как сделать правильно.

SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
CREATE OR REPLACE FUNCTION UPDATESALARYFORDEPARTMENT(IN INTEGER, IN INTEGER)
RETURNS TABLE 
(
"Departament_ID" INTEGER, 
"Должность" VARCHAR, 
"Должность руководителя" VARCHAR, 
"chiefid" INTEGER, "Зарплата руководителя" INTEGER, 
"Зарплата подчин. до индекс." INTEGER, 
"Зарплата подчин. после индекс." INTEGER, 
"Процент индексации зарплаты" INTEGER
)
AS 
$$
BEGIN RETURN query
WITH sup AS 
(
SELECT a.Departament_ID, 
a.Name AS "Должность",
b.Name AS "Должность руководителя", 
a.chief_id AS "chiefid", 
b.Salary AS "Зарплата руководителя", 
a.Salary AS "Зарплата подчин. до индекс.", 
(a.Salary*$2/100)+a.Salary AS "Зарплата подчин. после индекс.", 
$2 AS "Процент индексации зарплаты"
FROM Employee a
JOIN employee b ON b.departament_id = a.chief_id
WHERE a.Departament_ID = $1)
 
UPDATE Employee 
SET Salary=sup."Зарплата подчин. после индекс."
FROM sup 
WHERE sup."Зарплата руководителя"<sup."Зарплата подчин. после индекс." 
RETURNING *;
END;
$$
LANGUAGE plpgsql;
0
55 / 50 / 5
Регистрация: 30.06.2022
Сообщений: 251
02.05.2023, 14:33
Нужно обернуть запрос update в материализованную форму.
Поменять запрос на что-то вроде такого:
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
WITH sup AS 
(
SELECT
 a.Departament_ID, 
a.Name AS "Должность",
b.Name AS "Должность руководителя", 
a.chief_id AS "chiefid", 
b.Salary AS "Зарплата руководителя", 
a.Salary AS "Зарплата подчин. до индекс.", 
(a.Salary*$2/100)+a.Salary AS "Зарплата подчин. после индекс.", 
$2 AS "Процент индексации зарплаты"
FROM Employee a
JOIN employee b ON b.departament_id = a.chief_id
WHERE a.Departament_ID = $1),
upd AS
(
UPDATE Employee e
SET Salary=sup."Зарплата подчин. после индекс."
FROM sup s
WHERE 
s."Зарплата руководителя"<s."Зарплата подчин. после индекс." AND
s.departament_id=e.departament_id
RETURNING *
)
SELECT -- и вот этот обновлённый результат оно  RETURN-у подсунет
u."Departament_ID", 
u."Должность", 
u."Должность руководителя", 
u."chiefid" INTEGER, "Зарплата руководителя", 
u."Зарплата подчин. до индекс.", 
u."Зарплата подчин. после индекс.", 
u."Процент индексации зарплаты"
FROM upd u;
Employee должна содержать все поля, которые возвращает процедура, надо чтоб по типам подходили.
А вообще, со структурой похоже, бедулька, невнятно как-то. Почему структура отделов слеплена вместе с должностями? В частности chief_id что за поле? На что ссылается? Это надо догадываться? По-честноку, лениво очень.
0
14 / 13 / 1
Регистрация: 17.04.2023
Сообщений: 107
03.05.2023, 05:22  [ТС]
oktogen, спасибо.
chief_id это id руководителя департамента. То есть у департамента № 1 (departament_id) руководителем является директор №1 (chief_id=departament_id=5). Директора также имеют свои департаменты, но не имеют руководителей. Может быть структуру и получше можно было сделать, но мне главное с функцией разобраться.
Приведенный синтаксис не получается реализовать, а именно update выполнить в скобках невозможно. Ошибка синтаксиса пишется на этапе создания функции.
0
55 / 50 / 5
Регистрация: 30.06.2022
Сообщений: 251
03.05.2023, 07:06
результат
SQL
1
SELECT version();
Добавлено через 29 секунд
какой ?

Добавлено через 2 минуты
И какая ошибка(полный вывод сообщения)?

Добавлено через 2 минуты
Так же было бы неплохо привести
скрипт создания всех таблиц.
Реально не умею читать мысли))))
0
14 / 13 / 1
Регистрация: 17.04.2023
Сообщений: 107
03.05.2023, 10:50  [ТС]
oktogen, дополняю информацию:

1. Версия: PostgreSQL 15.2, compiled by Visual C++ build 1925, 64-bit

2. При создании функции ошибка синтаксиса (не при обращении к ней), после RETURNING обязательно должна быть ; но даже если поставить ; то все равно ошибка синтаксиса на ;
SQL state: 42601
Character: 976

3. Скрипты создания таблиц и заполнения данных.

SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*создание таблицы Departament*/
CREATE TABLE 
Departament
(
  pK_Departament_id serial PRIMARY KEY,
  Name VARCHAR (100) NOT NULL  
);
 
/*создание таблицы Employee*/
CREATE TABLE Employee
(
ID serial PRIMARY KEY, 
Departament_ID INTEGER,
Name VARCHAR (100) NOT NULL ,
chief_id INTEGER,
Salary INTEGER NOT NULL,
FOREIGN KEY (Departament_ID) REFERENCES Departament (pK_Departament_id),
FOREIGN KEY (chief_id) REFERENCES Employee (ID) 
);
 
 
/*заполнение таблицы Departament*/
INSERT INTO Departament (pK_Departament_id, name) 
VALUES
(1, 'Цех'),
(2, 'ООТиПБ'),
(3, 'Бухгалтерия'),
(4, 'Кадры'),
(5, 'Дирекция 1'),
(6, 'Дирекция 2'),
(7, 'Дирекция 3');
 
 
/*заполнение таблицы Employee*/
INSERT INTO Employee (Departament_id, chief_id, name, salary)
VALUES
(1, 5, 'Технолог цеха',45000),
(1, 5, 'Механик цеха',50000),
(1, 5, 'Начальник цеха',55000),
(1, 5, 'Инженер ППР',35000),
(2, 5, 'Инженер 1',35000),
(2, 5, 'Инженер 2',40000),
(2, 5, 'Инженер 3',45000),
(3, 6, 'Бухгалтер 1',40000),
(3, 6, 'Бухгалтер 2',50000),
(3, 6, 'Главный бухгалтер',210000),
(4, 7, 'Специалист 1',30000),
(4, 7, 'Специалист 2',40000),
(4, 7, 'Специалист 3',50000),
(5, NULL, 'Директор 1',100000),
(6, NULL, 'Директор 2',200000),
(7, NULL, 'Директор 3',300000)
0
55 / 50 / 5
Регистрация: 30.06.2022
Сообщений: 251
03.05.2023, 15:09
Лучший ответ Сообщение было отмечено andrey197888888 как решение

Решение

Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
CREATE OR REPLACE FUNCTION UPDATESALARYFORDEPARTMENT(IN INTEGER, IN INTEGER)
RETURNS TABLE 
(
id INTEGER,
Departament_ID INTEGER, 
"Должность" VARCHAR, 
"Должность руководителя" VARCHAR, 
"chiefid" INTEGER, 
"Зарплата руководителя" INTEGER, 
"Зарплата подчин. до индекс." INTEGER, 
"Зарплата подчин. после индекс." INTEGER, 
"Процент индексации зарплаты" INTEGER
)
AS 
$$
DECLARE
_rd RECORD;
BEGIN 
    FOR _rd IN
        SELECT
            a.id,
            a.Departament_ID, 
            a.Name AS "Должность",
            b.Name AS "Должность руководителя", 
            a.chief_id AS "chiefid", 
            b.Salary AS "Зарплата руководителя", 
            a.Salary AS "Зарплата подчин. до индекс.", 
            (a.Salary*$2/100)+a.Salary AS "Зарплата подчин. после индекс.", 
            $2 AS "Процент индексации зарплаты"
        FROM 
            Employee a
            JOIN employee b ON b.id = a.chief_id
        WHERE a.Departament_ID = $1
    LOOP
        UPDATE Employee e
        SET Salary=_rd."Зарплата подчин. после индекс."
        WHERE _rd.id=e.id;
        IF _rd."Зарплата руководителя"< _rd."Зарплата подчин. после индекс." THEN
            UPDATE Employee e
            SET Salary=_rd."Зарплата подчин. после индекс."
            WHERE _rd.chiefid=e.id;
            RETURN QUERY
            SELECT
                _rd.id,
                _rd.Departament_ID, 
                _rd."Должность", 
                _rd."Должность руководителя", 
                _rd."chiefid", 
                _rd."Зарплата подчин. после индекс." AS "Зарплата руководителя", 
                _rd."Зарплата подчин. до индекс.", 
                _rd."Зарплата подчин. после индекс.", 
                _rd."Процент индексации зарплаты";
        ELSE
            RETURN QUERY
            SELECT
                _rd.id,
                _rd.Departament_ID, 
                _rd."Должность", 
                _rd."Должность руководителя", 
                _rd."chiefid", 
                _rd."Зарплата руководителя", 
                _rd."Зарплата подчин. до индекс.", 
                _rd."Зарплата подчин. после индекс.", 
                _rd."Процент индексации зарплаты";
        END IF;
    END LOOP;
    RETURN;
END;
$$
LANGUAGE plpgsql;
вывод
Code
1
2
3
4
5
6
7
8
 select * from UPDATESALARYFORDEPARTMENT(1,45);
 id | departament_id |   Должность    | Должность руководителя | chiefid | Зарплата руководителя | Зарплата подчин. до индекс. | Зарплата подчин. после индекс. | Процент индексации зарплаты 
----+----------------+----------------+------------------------+---------+-----------------------+-----------------------------+--------------------------------+-----------------------------
  4 |              1 | Инженер ППР    | Инженер 1              |       5 |                 50750 |                       35000 |                          50750 |                          45
  3 |              1 | Начальник цеха | Инженер 1              |       5 |                 79750 |                       55000 |                          79750 |                          45
  2 |              1 | Механик цеха   | Инженер 1              |       5 |                 72500 |                       50000 |                          72500 |                          45
  1 |              1 | Технолог цеха  | Инженер 1              |       5 |                 65250 |                       45000 |                          65250 |                          45
(4 строки)
Добавлено через 2 минуты
Вот как-то так. Играйтесь с условиями, может что-то и зайдёт.
1
14 / 13 / 1
Регистрация: 17.04.2023
Сообщений: 107
05.05.2023, 09:32  [ТС]
oktogen, спасибо, буду разбираться, читать как работает. сам бы я до такой конструкции не смог дойти.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.05.2023, 09:32
Помогаю со студенческими работами здесь

Вызов хранимой процедуры из другой базы (PostgreSQL)
В базе данных basa1 имеется таблица Книга. Содержащуюся в ней информацию необходимо прочитать из базы данных basa2. В какой базе данных...

Реализация хранимой процедуры с переменным числом входных параметров
Посоветуйте как быть! каким образом реализовать ХП с переменным числом входных парметров причем кол-во переменых теоретически может...

Создание хранимой процедуры, которая создает хранимые процедуры
Написать хранимую процедуру SQL , которая будет создавать хранимые процедуры(любые) для БД.

Вызов процедуры из хранимой процедуры
подскажите плз. кто сталкивался по теме. необходима так же передача параметров. За ранее всем благодарен

Создание хранимой процедуры
Доброго времени суток, пытаюсь создать хранимую процедуру через запрос вида: CREATE PROCEDURE testBD.dbo.UpdateProc (@OKPO bigint,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru