使用数组中的每个元素调用集合返回函数

Posted

技术标签:

【中文标题】使用数组中的每个元素调用集合返回函数【英文标题】:Calling set-returning function with each element in array 【发布时间】:2013-02-06 16:06:51 【问题描述】:

我有一个集合返回函数 (SRF),它接受一个整数参数并从表中返回一组行。我使用SELECT * FROM tst.mySRF(3); 调用它,然后像处理表格一样操作返回的值。

我想做的是在数组的每个元素上执行它;但是,当我使用SELECT * FROM tst.mySRF(unnest(array[3,4])); 调用它时,会返回错误“在不能接受集合的上下文中调用的集合值函数”。如果我改为使用SELECT tst.mySRF(unnest(array[3,4])); 调用它,我会得到一组tst.tbl 类型。

表定义:

DROP TABLE tst.tbl CASCADE;
CREATE TABLE tst.tbl (
    id  serial  NOT NULL,
    txt text    NOT NULL,
    PRIMARY KEY (id)
);
INSERT INTO tst.tbl(txt) VALUES ('a'), ('b'), ('c'), ('d');

函数定义:

CREATE OR REPLACE FUNCTION tst.mySRF(
    IN  p_id            integer
)
    RETURNS setof tst.tbl
    LANGUAGE plpgsql
    AS $body$
        DECLARE
        BEGIN
            RETURN QUERY
                SELECT id, txt
                FROM tst.tbl
                WHERE id = p_id;
        END;
    $body$;

来电:

SELECT * FROM tst.mySRF(3) 按预期返回一个表。 正如预期的那样,SELECT tst.mySRF(unnest(array[3,4])) 返回一个包含 tst.tbl 类型的单列的表。 SELECT * FROM tst.mySRF(unnest(array[3,4])) 返回上面描述的错误,我期待一个表。

【问题讨论】:

是的。你写的是正确的。你的问题是什么?您不能在内部函数返回记录集的地方运行 select * from function(function())。 问题是如何在不使用一系列 UNION 语句的情况下,为数组的每个元素执行一个函数并获得一个表。 好吧,你展示了它 - 选择函数(other_function())。如果您出于某种原因不能这样做,在 9.3 上您可以使用 LATERAL,在以前的版本中 - 使用我在此处描述的工作方法:depesz.com/2012/08/19/… @depesz 但是 select function(other_function()) 返回的表是 tst.tbl 行的单列表。如何将其转换为 tst.tbl 类型的多列表?还是需要您提到的 9.3 功能? 【参考方案1】:

为避免“单列表”问题,您需要使用(row).* 符号显式扩展 SRF 结果

 SELECT (tst.mySRF(unnest(array[3,4]))).*;

如果我理解@depesz,LATERAL 将提供一种更有效或更直接的方式来实现相同的结果。

【讨论】:

以上是关于使用数组中的每个元素调用集合返回函数的主要内容,如果未能解决你的问题,请参考以下文章

JS中的map()函数

oracle怎么使用数组

数组迭代

js中filter函数

遍历数组元素的方法

函数式编程之实践