从 PL/pgSQL 返回查询

Returning Query from PL/pgSQL

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

假设我想运行查询以获取 Sandrine (emp_id = 63679) 整个命令链的所有列(即 Sandrine、Sandrine 的老板、Sandrine 的老板的老板等) .)

我将如何编写此查询?

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

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;

数据库看起来像这样:

您的函数有几个错误。

  1. 您 select 来自名为 employees 的 table,因此函数应该 return setof employees,而不是 "person"
  2. 你没有在任何地方存储 select 的结果,所以你不能实际分配 "counter" 变量(这对于变量名来说是一个非常糟糕的选择)
  3. execute 只有动态 SQL 才需要,如果你有静态 SQL
  4. 则不需要
  5. 您应该将员工 ID 作为参数传递,而不是对其进行硬编码。

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

将所有这些放在一起,您的函数应该如下所示:

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;