在函数 PLpgSQL 的查询中使用行作为 table

Using a row as a table in a query within a function PLpgSQL

我正在尝试编写一个循环遍历 table 的 plpgsql 函数。在每个循环中,它从 table 中提取一行,将其存储在一条记录中,然后在查询的连接子句中使用该记录。这是我的代码:

CREATE OR REPLACE FUNCTION "testfncjh2" ()  RETURNS int
  IMMUTABLE
  SECURITY DEFINER
AS $dbvis$
DECLARE 
        counter int;
        tablesize int;
        rec1 record;
        tablename text;
        rec2 record;
BEGIN
counter = 0;
for rec1 in  SELECT * FROM poilocations_sridconv loop  

raise notice 'here';   
execute $$ select count(*) from $$||rec1||$$ $$ into tablesize;

        while counter < tablesize loop

                counter = counter + 1;
                raise notice 'hi';
                execute $$ select count(*) from cities_sridconv $$ into tablesize;
                end loop; 
    end loop;
return counter;
END;
$dbvis$ LANGUAGE plpgsql;

每次我运行这个,我得到以下错误:

ERROR: could not find array type for data type record

有没有办法在嵌套循环的查询中将该行用作 table?

我的最终目标是构建一个循环遍历 table 的函数,在每个循环中从 table 中拉出一行。在每个循环中,使用该行计算一个数字 COUNTER,然后根据该行和 COUNTER 执行查询。知道这段代码目前存在很大缺陷,我将其发布在下面以了解我正在尝试做什么:

创建或替换函数 "testfncjh" () RETURNS void 不变的 安全定义者 作为 $dbvis$ 宣布 计数器; table大小整数; rec1记录; table姓名文字; rec2记录; 开始

for rec1 in  SELECT * FROM poilocations_sridconv loop  
        counter = 0;
        execute $$ select count(*)
                from    $$||rec1||$$ a
                join
                        cities_srid_conv b
                on      right(a.geom_wgs_pois,$$||counter||$$) = right(b.geom_wgs_pois,$$||counter||$$) $$ into tablesize;

        raise notice 'got through first execute';
        while tablesize = 0 loop

                counter = counter + 1;
                execute $$ select count(*)
                from    '||rec1||' a
                join
                        cities_srid_conv b
                on      right(a.geom_wgs_pois,'||counter||') = right(b.geom_wgs_pois,'||counter||') $$ into tablesize;
                raise notice 'hi';
                end loop;

        EXECUTE
                'select 
                         poiname,
                         name as cityname, 
                         postgis.ST_Distance(postgis.ST_GeomFromText(''POINT(poilat poilong)''),
                                             postgis.ST_GeomFromText(''POINT(citylat citylong)'')
                                             ) as distance
                from    (select a.poiname, 
                                a.latitude::text as poilat, 
                                a.longitude::text as poilong,
                                b.geonameid, 
                                b.name, 
                                b.latitude as citylat, 
                                b.longitude as citylong
                        from '||rec1||' a 
                        join cities_srid_conv b
                        on  right(a.geom_wgs_pois,'||counter||') = right(b.geom_wgs_pois,'||counter||'))
                        ) x
                 order by distance
         limit 1'

        poi_cities_match (poiname, cityname, distance);  ------SQL STATEMENT TO INSERT CLOSEST CITY TO TABLE POI_CITIES_MATCH 
    end loop;

END;
$dbvis$ LANGUAGE plpgsql;

我运行正在使用 PostgreSQL 8.2.15 数据库。

另外,很抱歉重新发布。我不得不从原始数据中删除一些数据。

我认为您应该能够根据需要使用复合类型。我简化了您的顶级示例并按以下方式使用了复合类型。

CREATE OR REPLACE FUNCTION "testfncjh2" ()  RETURNS int
  IMMUTABLE
  SECURITY DEFINER
AS $dbvis$
DECLARE 
        counter int;
        tablesize int;
        rec1 poilocations_sridconv;
        tablename text;
        rec2 record;
BEGIN
counter = 0;
for rec1 in  SELECT * FROM poilocations_sridconv loop  
  raise notice 'here';
  select count(*) FROM (select (rec1).*)theRecord into counter; 
end loop;
return counter;
END;
$dbvis$ LANGUAGE plpgsql;

主要变化是 rec1 poilocations_sridconv; 行和使用 (select (rec1).*)

希望对您有所帮助。

编辑:我应该注意到该函数的作用与上面的问题不同。这只是一个示例,说明如何在查询中将记录用作 table。

您的代码存在一些问题(除了您的逻辑之外)。

最重要的是,您不应将 record 用作 JOIN 中的 table 来源。相反,过滤第二个 table 以查找与 record.

中的某些字段匹配的行

其次,您应该使用 format() 函数而不是使用 || 运算符组装字符串。但是你不能,因为你使用的是史前版本 8.2。这是洞穴绘画时代的作品(是的,就是那么糟糕)。升级!

第三,不要使您的查询过于复杂。这里不需要子查询。

放在一起,您的真实代码中的第二个动态查询将减少为:

EXECUTE format(
  'SELECT b.name, 
          postgis.ST_Distance(postgis.ST_SetSRID(postgis.ST_MakePoint(%1$I.longitude, %1$I.latitude), 4326),
                              postgis.ST_SetSRID(postgis.ST_MakePoint(b.longitude, b.latitude), 4326))
   FROM cities_srid_conv b
   WHERE right(%1$I.geom_wgs_pois, %2$L) = right(b.geom_wgs_pois, %2$L)
   ORDER BY distance
   LIMIT 1', rec1, counter) INTO cityname, distance;

poi_cities_match (rec1.poiname, cityname, distance);  ------SQL STATEMENT TO INSERT CLOSEST CITY TO TABLE POI_CITIES_MATCH 

这里的%1$I指的是字符串后面的第一个参数,是一个标识符:rec1%2$L 是第二个参数,是一个文字值:counter。我留给您自己将其重新处理为 8.4 之前的字符串连接。查询的结果存储在一些额外的变量中,您可以在接下来的函数调用中使用这些变量。

最后,您将 longitudelatitude 颠倒了。在 PostGIS 中 longitude 总是第一位。