PostgreSQL 函数如何接受同一函数的整数或整数数组?
How can a PostgreSQL function accept an integer or array of integers for the same function?
我在 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]
?
无法在单个函数中处理此问题,但您可以使用 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
的论点,这取决于您。
它是可以使用VARIADIC
修饰符的单个函数:
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);
如果这不是一个选项,您将返回另一个答案中建议的函数重载。
参见:
- Pass multiple values in single parameter
旁白
- 看起来这可以是一个更简单的 SQL 函数。
UNION
没有意义。仅当您的树绕圈时才会出现重复,这会产生无限循环并且 rCTE 会出错。使用更便宜的 UNION ALL
.
LEFT JOIN
没有意义。添加的 WHERE
迫使它表现得像普通的 [INNER] JOIN
一样。
- 但是完全删除连接并检索 rCTE 中的列
disabled
。
我在 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]
?
无法在单个函数中处理此问题,但您可以使用 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
的论点,这取决于您。
它是可以使用VARIADIC
修饰符的单个函数:
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);
如果这不是一个选项,您将返回另一个答案中建议的函数重载。
参见:
- Pass multiple values in single parameter
旁白
- 看起来这可以是一个更简单的 SQL 函数。
UNION
没有意义。仅当您的树绕圈时才会出现重复,这会产生无限循环并且 rCTE 会出错。使用更便宜的UNION ALL
.LEFT JOIN
没有意义。添加的WHERE
迫使它表现得像普通的[INNER] JOIN
一样。- 但是完全删除连接并检索 rCTE 中的列
disabled
。