从PL / pgSQL返回查询

时间:2020-04-02 02:12:37

标签: sql postgresql plpgsql recursive-query

我有一个记录列表,其中包含每个员工的员工ID(emp_id)和其经理的员工ID(manager_id)

让我们说我想运行一个查询来获取Sandrine的整个命令链的所有列(emp_id = 63679)(即Sandrine,Sandrine的老板,Sandrine的老板的老板等)

我将如何编写此查询?

我在PL / pgSQL中尝试了以下循环:

SELECT name
FROM student
WHERE course IN ('LAWS0001', 'LAWS0002')

数据库看起来像这样:

SQL Exercise Dataset

1 个答案:

答案 0 :(得分:0)

您的函数有几个错误。

  1. 您正在从名为employees的表中进行选择,因此该函数应返回setof employees,而不是“ person”
  2. 您不会将选择的结果存储在任何地方,因此您实际上无法分配“计数器”变量(对于变量名,这确实是一个糟糕的选择)
  3. execute仅用于动态SQL,如果您具有静态SQL,则不需要
  4. 您应该将员工的ID作为参数开头,而不是对其进行硬编码。

因此,为了实际使用检索到的行,需要将其存储在变量中,该变量可以定义为与结果表相同的类型。

将所有内容放在一起,您的函数应如下所示:

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);

但是,不需要编写函数来遍历这样的层次结构。这可以通过使用recursive common table expression

的单个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;