返回游标结果

时间:2012-05-06 12:19:56

标签: postgresql cursor resultset plpgsql sql-returning

我有以下程序:

CREATE OR REPLACE FUNCTION findKNN()
RETURNS Text AS $body$
DECLARE
    cur refcursor;
    tempcur refcursor;
    gid_ integer;
    _var1 integer;
    _var2 integer;
BEGIN
    open cur for execute('select gid from polygons');
    loop
    fetch cur into gid_;
    open tempcur for SELECT g1.gid , g2.gid FROM polygons AS g1, polygons AS g2
    WHERE g1.gid = gid_  and g1.gid <> g2.gid ORDER BY g1.gid , ST_Distance(g1.the_geom,g2.the_geom)
        LIMIT 5;
             loop
                 fetch tempcur into _var1 , _var2;
                     -- how to return _var1 , _var2 here ? 
                 end loop;
          end loop;
                close cur;
    END;
$body$
LANGUAGE plpgsql;

但我不知道如何从这个程序中返回结果。对于外部游标循环中的每次执行,查询返回5行。如何为每个查询执行检索这五行?

1 个答案:

答案 0 :(得分:3)

除非您尝试做一些不在您问题中的更复杂的事情,否则您可以从根本上简化为:

CREATE OR REPLACE FUNCTION find_knn()
    RETURNS TABLE(gid1 integer, gid2 integer)  AS
$body$
BEGIN

    RETURN QUERY
    SELECT g1.gid , g2.gid
    FROM   polygons g1
    JOIN   polygons g2 ON g1.gid <> g2.gid
    -- WHERE  g1.gid = <some_condition>  -- ???
    ORDER  BY g1.gid, st_distance(g1.the_geom, g2.the_geom)
    LIMIT  5;

END;
$body$    LANGUAGE plpgsql;

甚至:

CREATE OR REPLACE FUNCTION find_knn()
    RETURNS TABLE(gid1 integer, gid2 integer)  AS
$body$
    SELECT g1.gid , g2.gid
    FROM   polygons g1
    JOIN   polygons g2 ON g1.gid <> g2.gid
    -- WHERE  g1.gid = <some_condition>  -- ???
    ORDER  BY g1.gid, st_distance(g1.the_geom, g2.the_geom)
    LIMIT  5;
$body$    LANGUAGE sql;

呼叫:

SELECT * FROM x.find_knn();

关于Returning From a Function的手册 有关CREATE FUNCTION

的手册

检索一个巨大连接的一小部分

(回答评论。)
有很多方法可以在不实际评估整个连接的情况下选择一小部分巨大连接。在大多数情况下,您甚至不必担心它。例如,在家里运行:

EXPLAIN ANALYZE
SELECT *
FROM   huge_tbl t1
CROSS  JOIN huge_tbl t2
LIMIT  5

您将看到只处理5行,整个交叉联接 CTE

也是如此
WITH a AS (
    SELECT *
    FROM   huge_tbl t1
    CROSS JOIN huge_tbl t2
    )
SELECT *
FROM   a
LIMIT  5

有一些限制。我引用excellent manual

  

PostgreSQL的实现仅评估WITH的多行   查询是父查询实际获取的。

为了绝对确定,您可以在源头应用LIMIT(或拟合WHERE子句):

SELECT *
FROM   (SELECT * FROM huge_table LIMIT 1) t1
CROSS  JOIN (SELECT * FROM huge_table LIMIT 5) t2;
相关问题