【问题标题】:Returning cursor results返回游标结果
【发布时间】:2012-05-15 06:32:55
【问题描述】:

我有以下程序:

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 行。如何为每个查询执行检索这五行?

【问题讨论】:

    标签: postgresql cursor resultset plpgsql sql-returning


    【解决方案1】:

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

    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;
    

    【讨论】:

    • +1 至少 90% 的时间我看到使用了光标,这不是解决手头问题的最佳方法。任何时候任何人在考虑使用光标时,都应该退后一步,看看有哪些替代方案。
    • @kgrittn:没错!在极少数情况下,游标是最佳解决方案,同样,大多数情况下最好使用 FOR LOOP 的内置游标。
    • @ErwinBrandstetter 先生,这就是我不想要的。您的解决方案是完全正确的,但我不想完全在两个表之间执行 JOIN,因为表很大并且它确实会破坏查询执行。我需要的是迭代表多边形表,并且对于每个 gid,我想使用 where 条件最小化 JOIN 操作的负载。这就是为什么我为此目的使用外部光标。我认为你应该参考这个:bostongis.com/…
    • @AbhishekSagar:我在回答中添加了一些内容。如果这不能解决您的问题,请澄清您的问题,您实际上正在尝试做什么。
    • @ErwinBrandstetter,我的问题是,我有一个多边形表。对于每个多边形,我需要根据欧几里得距离找到最近的多边形。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2016-08-23
    • 1970-01-01
    相关资源
    最近更新 更多