我正在尝试编写一个循环遍历表的plpgsql函数。在每个循环中,它从表中提取一行,将其存储在记录中,然后在查询的join子句中使用该记录。这是我的代码:
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”()RETURNS void IMMUTABLE 安全定义者 AS $ dbvis $ 宣布 反int; tablesize int; rec1记录; tablename文本; rec2记录; BEGIN
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数据库上运行。
另外,抱歉重新发布。我不得不从原文中删除一些数据。
答案 0 :(得分:0)
我认为您应该能够根据需要使用复合类型。我简化了您的顶级示例,并按以下方式使用了复合类型。
LANGUAGES = (
('sr-latn', 'Srpski'),
('en', 'English'),
)
主要更改为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;
希望它有所帮助。
编辑:我应该注意到该函数与上面的问题没有做同样的事情。这只是一个如何在记录中将记录用作表格的示例。
答案 1 :(得分:0)
您的代码存在一些问题(或许,可能来自您的逻辑)。
最重要的是,您不应在record
中使用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
被撤消了。在PostGIS longitude
中始终是第一位的。