具有数组值的 CTE 的 Postgres 递归构建

Postgres recursive building of CTE with array values

我有一个表示函数名称的字符串数组。我需要遍历它们才能调用每个函数。它们根据与函数中其他 table 匹配的条件来区分行。我需要单独查询的累积行,并且认为递归 CTE 是可行的方法。但是,我无法增加引用数组索引的数字。有什么建议吗?此外,如果这只是一个糟糕的方法,任何提示都会很棒 :D

CREATE OR REPLACE FUNCTION fn_name(target_table TEXT, identifier INT) returns setof table_name as
$$
DECLARE
 function_names text[];
BEGIN
  function_names := '{fn1, fn2, fn3}';
  WITH RECURSIVE non_matches(n) as (
    SELECT * FROM non_matching_records(, , function_names[1])
    UNION
    SELECT * FROM non_match_records(, , function_names[n+1] 
      WHERE n < ARRAY_LENGTH(function_names, 1) + 1
  )
  SELECT * FROM non_matches;
END
$$ LANGUAGE plpgsql;

编辑: 删除了对相同 table return 的引用。我忘了这就是我接受 table 参数的原因,这样它就可以 return 无效。我需要从每个函数 returned 收集记录,以便能够 运行 对它们进行另一个查询。

更新:

这里是我的递归查询 atm:

WITH RECURSIVE non_matches AS (
        SELECT *, 1 AS depth FROM non_matching_records(, , function_names[1])
        UNION
        SELECT c.*, nm.depth + 1 AS depth FROM non_matching_records(, , function_names[nm.depth]) c, non_matches nm
    )
    SELECT * FROM non_matches;

我从这次更新中收到的错误是没有名为 depth 的列,如果我不包括 CTE 名称。如果我使用它,则没有 CTE 条目。不太确定如何访问括号中的内容以访问数组。

non_matching_records 是一个查找不匹配记录的函数。

我会遍历数组并使用 RETURN QUERY EXECUTE 调用每个函数。

CREATE OR REPLACE FUNCTION fn_name(target_table regclass, identifier INT) returns setof table_name AS
$$
DECLARE 
  function_names regproc[] := '{fn1, fn2, fn3}';
  fn regproc;
BEGIN
  FOREACH fn IN ARRAY function_names
  LOOP
    RETURN QUERY EXECUTE format('SELECT * FROM %s(%s, %L)', fn, , );
  END LOOP;
  RETURN;
END;
$$ LANGUAGE PLPGSQL;

我在这里使用了 regclass 和 regproc 来帮助对表和函数进行模式限定,但是您可以将它们改回文本,只要您注意它们的调用方式即可。

昨晚终于搞定了。事实证明,一旦我添加了 depth 列,我最初从 中选择了 错误的 'table'。我切换了表的顺序,首先是 cte,然后 然后 与 returns 记录的函数连接。这使我可以访问深度列并允许我增加索引

WITH RECURSIVE non_matches AS (
        SELECT c.*, 1 AS depth FROM non_matching_records(, , function_names[1]) c
        UNION
        SELECT c.*, nm.depth + 1 as depth 
        FROM non_matches nm, non_matching_records(, , function_names[nm.depth]) c
        WHERE nm.depth < array_length(match_rules, 1) + 1
    )