PostgreSQL函数如何为同一函数接受整数或整数数组?

问题描述 投票:1回答:2

我在Postgres 9.6中有一个接受int[]参数的函数。我想让该函数也接受单个int(并在必要时将其转换为单个元素数组)。

 CREATE OR REPLACE FUNCTION get_subordinates(inp_persona_ids integer[])
 -- Get all subordnates of the people passed in as array
 -- TODO allow a single persona ID (int) to be passed in as inp_persona_ids
 RETURNS TABLE (persona_id int) AS
 $$
    BEGIN
        RETURN QUERY(
            WITH RECURSIVE children AS (
                -- passed in persona_id
                SELECT
                    id AS persona_id,
                    manager_id
                FROM
                    personas
                WHERE
                    id = ANY(inp_persona_ids)
                UNION
                -- and all subordinates
                SELECT
                    p.id AS persona_id,
                    p.manager_id
                FROM
                    personas p
                    JOIN children c ON p.manager_id = c.persona_id
            )
            SELECT 
                children.persona_id
            FROM
                children
            LEFT JOIN
                personas on children.persona_id = personas.id
            WHERE personas.disabled IS NOT TRUE
        );
    END;
$$ LANGUAGE plpgsql

我将如何更改函数定义,并添加一些条件逻辑来测试int,并在必要时更改为ARRAY[int]

arrays postgresql types plpgsql postgresql-9.6
2个回答
1
投票

不可能在单个函数中处理,但是您可以使用integer参数重载该函数并将其作为数组传递给现有函数:

CREATE OR REPLACE FUNCTION get_subordinates(inp_persona_id integer)
RETURNS TABLE (persona_id int) AS
$$
BEGIN
    RETURN QUERY SELECT * FROM get_subordinates(ARRAY[inp_persona_id]);
END;
$$ LANGUAGE plpgsql;

也许您可能还想根据NULL检查参数,这取决于您。


0
投票

使用VARIADIC修饰符使用单个功能可以实现[[<< [is

CREATE OR REPLACE FUNCTION get_subordinates(VARIADIC inp_persona_ids int[]) RETURNS TABLE (persona_id int) AS $func$ WITH RECURSIVE children AS ( -- passed in persona_id SELECT id AS persona_id, manager_id, disabled FROM personas WHERE id = ANY(inp_persona_ids) UNION ALL -- and all subordinates SELECT p.id AS persona_id , p.manager_id FROM children c JOIN personas p ON p.manager_id = c.persona_id ) SELECT c.persona_id FROM children c WHERE c.disabled IS NOT TRUE $func$ LANGUAGE sql;
但是
在提供数组而不是列表时,需要在调用中添加关键字VARIADIC

SELECT * FROM get_subordinates(VARIADIC '{1,2,3}'::int[]); SELECT * FROM get_subordinates(1,2,3); SELECT * FROM get_subordinates(1); 如果这不是一个选择,您将按照另一个答案中的建议返回功能重载。

见:

Passing multiple values in single parameter

  • 旁白
  • 看起来像这样可能是一个更简单的SQL函数。

    • UNION毫无意义。仅当您的树绕圈旋转时才会发生重复,这将导致无限循环,并且rCTE会出错。使用便宜的UNION ALL
    • LEFT JOIN毫无意义。无论如何,添加的WHERE强制其表现得​​像普通的[INNER] JOIN
    • 但是要完全删除连接并在rCTE中检索列disabled
    © www.soinside.com 2019 - 2024. All rights reserved.