Возврат запроса из PL / pgSQL - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть список записей, в которых есть идентификаторы сотрудников для каждого сотрудника (emp_id) и идентификатор сотрудника их менеджера (manager_id)

Допустим, я хотел запустить запрос, чтобы получить все столбцы для всей цепочки команды для Сандрин (emp_id = 63679) (т. е. Сандрин, босс Сандрин, босс босса Сандрин и др. c.)

Как мне написать этот запрос?

Я пробовал следующее l oop в PL / pg SQL:

CREATE FUNCTION getpersons() RETURNS SETOF person
LANGUAGE plpgsql AS
$$ Declare
counter INTEGER := 63679 ;
Begin
WHILE (Counter is not null) loop
RETURN QUERY EXECUTE (SELECT * FROM employees WHERE employees.emp_id = Counter);
Counter = employees.manager_id;
END LOOP;
END; $$
SELECT * from person;

БД выглядит так:

SQL Exercise Dataset

1 Ответ

0 голосов
/ 02 апреля 2020

Ваша функция имеет несколько ошибок.

  1. вы выбираете из таблицы с именем employees, поэтому функция должна возвращать setof employees, а не "person"
  2. Вы не сохраните результат выбора нигде таким образом, вы не можете назначить переменную counter (которая является действительно плохим выбором для имени переменной) stati c SQL
  3. Вы должны передать идентификатор сотрудника для начала в качестве параметра, а не жестко его кодировать.

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

Собрав все это вместе, ваша функция должна выглядеть следующим образом:

CREATE FUNCTION getpersons(p_startid integer) 
  RETURNS SETOF employee
LANGUAGE plpgsql AS
$$ Declare
  l_id INTEGER := p_startid;
  l_row employee;
Begin
  WHILE (l_id is not null) loop
    SELECT * 
      into l_row
    FROM employee 
    WHERE emp_id = l_id;

    l_id := l_row.manager_id;
    return next l_row;
  END LOOP;
END; 
$$
;

Тогда вы можете использовать это так:

select *
from getpersons(63679);

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

with recursive persons as (
  select *
  from employees
  where id = 63679 
  union all 
  select ch.*
  from employees ch
    join persons p on p.manager_id = ch.id
)
select *
from persons;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...