0

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

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;

每次我运行它时,我都会收到以下错误:

错误:找不到数据类型记录的数组类型

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

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

创建或替换函数 "testfncjh" () 返回 void IMMUTABLE SECURITY DEFINER AS $dbvis$ DECLARE counter int; 表格大小 int; rec1 记录;表名文本;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 数据库上运行。

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

4

2 回答 2

0

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

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).*)

希望能帮助到你。

编辑:我应该注意,该功能与上述问题中的功能不同。这只是作为如何在查询中将记录用作表的示例。

于 2016-03-02T23:13:17.223 回答
0

您的代码存在一些问题(可能与您的逻辑不同)。

首先,您不应该record在 a 中使用 a 作为表源JOIN。相反,过滤第二个表以查找与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 之前的字符串连接。查询的结果存储在几个附加变量中,然后您可以在以下函数调用中使用这些变量。

最后,你已经longitude逆转latitude了。在 PostGISlongitude中始终是第一位的。

于 2016-03-02T23:51:06.257 回答