我创建了以下存储过程,它应该返回与多边形组交叉的所有位置名称(没有明显的...与3个多边形的交集=> 3个名称)
CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time TIMESTAMP,
end_time TIMESTAMP,
polygon_group_id INTEGER)
RETURNS TABLE(name_name_name_name VARCHAR(12)) AS $$
DECLARE
name VARCHAR(12);
poly_id INTEGER;
BEGIN
FOR poly_id IN (SELECT polygon_id
FROM polygon_group_members
WHERE group_id = poly_id)
LOOP
FOR name IN (SELECT DISTINCT name
FROM location, polygons
WHERE location.timestamp BETWEEN start_time AND end_time
AND poly_id = polygons.id
AND st_intersects(location.polygon, polygons.polygon))
LOOP
RETURN NEXT name;
END LOOP;
END LOOP;
RETURN;
END;
$$ LANGUAGE SQL;
当我尝试创建此功能时,出现以下错误:
[42601]错误:语法错误位于或接近“VARCHAR”位置:356
基于PostgreSQL declaration documentation似乎没问题......
到目前为止我尝试过:
我将name VARCHAR(12);
更改为name location.mac%TYPE
我将name VARCHAR(12);
更改为name RECORD
我更改了声明的范围,然后我在poly_id INTEGER;
我将LANGUAGE SQL
更改为postgressql
我用Google搜索,根据任何示例/问题,我发现此程序应该有效。
答案 0 :(得分:1)
你不需要PL / pgSQL。循环是不必要的,将使一切都很慢。
据我所知,应该这样做:
CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time TIMESTAMP,
end_time TIMESTAMP,
polygon_group_id INTEGER)
RETURNS TABLE(name_name_name_name VARCHAR(12))
AS
$$
SELECT DISTINCT name
FROM location, polygons
WHERE location.timestamp BETWEEN start_time AND end_time
AND poly_id IN (SELECT polygon_id FROM polygon_group_members WHERE group_id = polygon_group_id)
AND st_intersects(location.polygon, polygons.polygon));
$$
LANGUAGE SQL;
我还认为条件WHERE group_id = poly_id
是错误的,因为您正在使用应该将结果存储在where
子句中的变量。我认为您打算使用WHERE group_id = polygon_group_id
(我在上面的代码中对此进行了更改)
使用language sql
时,您无法使用begin ... end
等过程代码或声明变量。
错误ERROR: syntax error at or near "VARCHAR" Position: 356
是由使用language sql
但在函数体内使用PL / pgSQL引起的。如果您在定义中将language sql
更改为language plpgsql
,它应该可以正常工作(但是,具有两个嵌套循环的解决方案效率不高)。
答案 1 :(得分:1)
感谢@ a_horse_with_no_name的评论指出我$$ LANGUAGE SQL
应该是$$ LANGUAGE plpgsql
我找到了解决方案。
在我更改为$$ LANGUAGE plpgsql
后,我收到了关于丢失OUT PARAMETER
的新错误,但OUT PARAMETER
不允许RETURN NEXT
,因此我不得不返回SETOF
而不是TABLE
{1}}:
CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time TIMESTAMP,
end_time TIMESTAMP,
polygon_group_id INTEGER)
RETURNS SETOF VARCHAR(12) AS $$
DECLARE
name VARCHAR(12);
poly_id INTEGER;
BEGIN
FOR poly_id IN (SELECT polygon_id
FROM polygon_group_members
WHERE group_id = poly_id)
LOOP
FOR name IN (SELECT DISTINCT name
FROM location, polygons
WHERE location.timestamp BETWEEN start_time AND end_time
AND poly_id = polygons.id
AND st_intersects(location.polygon, polygons.polygon))
LOOP
RETURN NEXT name;
END LOOP;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
答案 2 :(得分:1)
你提出的答案仍有几个问题。你可以很好地使用RETURNS TABLE()
。比较:
CREATE OR REPLACE FUNCTION get_name_without_distinct_by_polygon_group(start_time timestamp,
end_time timestamp,
polygon_group_id int)
RETURNS TABLE(name_name_name_name VARCHAR(12)) AS
$func$
DECLARE
name VARCHAR(12); -- possible naming conflict!
poly_id int;
BEGIN
FOR poly_id IN -- no parentheses needed
SELECT polygon_id
FROM polygon_group_members
WHERE group_id = poly_id -- I suspect you really want polygon_group_id here
LOOP
FOR name_name_name_name IN -- assign directly
SELECT DISTINCT name -- l.name or p.name??
FROM polygons p
JOIN location l ON st_intersects(l.polygon, p.polygon)
WHERE p.id = poly_id
AND l.timestamp BETWEEN start_time AND end_time
LOOP
RETURN NEXT; -- already assigned
END LOOP;
END LOOP;
RETURN;
END
$func$ LANGUAGE plpgsql;
请注意可能的命名冲突。所有声明的变量和参数(包括RETURNS TABLE()
子句中的字段在plpgsql或SQL函数体内的SQL查询中都是可见的。一种普遍的约定是在变量名前加上_
和表限定查询中的所有列。请参阅今天的早期答案:
整个函数可能会被一个SELECT
语句替换。