【问题标题】:pl/pgsql does not return all the results using recordpl/pgsql 不使用记录返回所有结果
【发布时间】:2018-01-30 23:24:31
【问题描述】:

我正在尝试创建一个复杂的 pl/pgsql 函数,该函数从查询中收集一些结果,然后检查每个结果并返回或不返回。

这是我的代码到目前为止recordloop 部分让我感到困惑。

CREATE  FUNCTION __a_search_creator(creator text, ordertype integer, orderdate integer, areaid bigint) RETURNS record
AS $$
DECLARE    
fromText text;
whereText text;
usingText text; 
firstrecord record;
areageom geometry;

BEGIN
    IF areaid IS NOT NULL
    THEN        
        EXECUTE format('SELECT area.geom FROM area WHERE area.id=$1')
        INTO areageom
        USING areaid;  

        FOR firstrecord IN 
        EXECUTE format( 
        'SELECT place.id, person.name, place.geom 
        FROM '||fromText||'     
        WHERE '||whereText)  
        USING  creator, ordertype , orderdate         
        LOOP    
        --return only data that the place.geom is inside areageom using PostGIS 
        END LOOP;
    END IF;
    RETURN firstrecord;
END;
$$
LANGUAGE plpgsql;

我计划loop 中进行一些额外的检查,如您所见,RETURN 只有place.geom(经度/纬度)在areageom 内的数据。但是由于我是 pl/pgsql 的新手,所以我现在创建第一步,只是收集所有数据,将它们放入 record 并返回。

我的问题是,无论我尝试什么,我都只能得到一个结果。我打电话给select __a_search_creator('johnson',8, 19911109, 20);,我得到1,"seth johnson", 65485,84545,但我知道我应该得到另一行结果。是否发生覆盖?

我试过把RETURN NEXT firstrecord;我试过类似的东西

        select place.id from place INTO placeid;        
        select person.name from person INTO personname;
        select place.geom from place INTO placegeom;        
        firstrecord.id := placeid;
        firstrecord.name := personname;
        firstrecord.geom := placegeom;

这仍然只带回一个结果,我尝试只测试这个RAISE NOTICE '%', firstrecord.id;,它仍然只带回一组完整的结果。

我不知道该怎么做,请指教。

【问题讨论】:

  • 不相关,但是:第一个查询中的动态SQL没用。您可以将其替换为普通的 SELECT area.geom INTO areageom FROM area WHERE area.id = areaid;

标签: postgresql for-loop plpgsql resultset set-returning-functions


【解决方案1】:

您使用RETURNS record 声明了您的函数,因此它返回一个单个 记录(类型未知)。

使用RETURNS SETOF record 返回一组行。 The manual:

SETOF 修饰符表示该函数将返回一组项目,而不是单个项目。

更好的是,使用 RETURNS TABLE 和适当的表定义。就像您在最近的问题中已经提出的那样:

相关(附有详细解释和手册链接):

【讨论】:

    【解决方案2】:

    这是我对问题的解决方案

    IF areaid IS NOT NULL
    THEN                        
        EXECUTE format('SELECT area.geom FROM area WHERE area.id=$1')
        INTO areageom
        USING areaid;                      
    
        FOR firstrecord IN 
        EXECUTE format( 
        'SELECT place.id, person.name, place.geom FROM '||fromText||' WHERE '||whereText)          
        USING  creator, ordertype, orderdate
    
        LOOP
            IF ST_Within(firstrecord.geom , areageom)
            THEN
                RETURN QUERY VALUES(firstrecord.id, firstrecord.name, firstrecord.geom);
            END IF;
        END LOOP;        
    END IF;
    RETURN; 
    

    感谢@Erwin Brandstetter 提供有用的链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多