在动态查询中使用几何数据类型

时间:2016-01-21 03:11:13

标签: postgresql postgis

我正在使用PostGIS在PostgreSQL中创建一个函数,我接受表名和点的几何,我想在函数内部的查询中使用它们......

CREATE OR REPLACE FUNCTION trial(tbl text[],tag text[],geo geometry)
RETURNS boolean AS
$BODY$
DECLARE i integer;
DECLARE len integer;
DECLARE result boolean;
DECLARE bool boolean;

BEGIN
    result=true;
    SELECT ARRAY_LENGTH(tbl,1) INTO len;
    FOR i IN 1..len LOOP
    EXECUTE format('select st_dwithin(geo::geography,geom::geography,1) from %s where name=any(array[%s]) and st_dwithin(geo::geography,geom::geography,1)=true',tbl[i],tag[i]) into bool;

        IF (bool!=true) THEN
        result=false;
        EXIT;
        END IF;

    END LOOP;
    return result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

这显示错误为

LINE 1: select st_dwithin(geo::geography,geom::geography,1) from grn... 

当我使用

  

该几何的%s

我收到了下一个错误

ERROR:  syntax error at or near "AA40E9A0E5440F498329474092A40"
LINE 1: select st_dwithin(0101000020E6100000002AA40E9A0E5440F4983294...

我是PostgreSQL的初学者...在这种情况下我可以使用什么格式说明符?????

1 个答案:

答案 0 :(得分:1)

您的功能存在一些问题。

首先,在format()函数中,您只能传递标识符和文字值,而需要传递函数的geographytext[]两个参数。这基本上意味着您无法使用format()功能,但您应该use the USING clause。顺便说一下,这是个好消息,因为format()生成一个字符串并且效率非常低(你传入一个geometry,它被format()转换为字符串,然后被解析回{ {1}}在服务器中,每次迭代循环一次)。作为PL / pgSQL变量的geometry参数将不会由geo解析,因此它也必须通过EXECUTE子句提供。

动态查询本身也不是特别好。逻辑表示如果USING中至少有一行距true 1米范围内,则要返回tags。有效编写,该查询将是:

geo

这显然假设所有表格都有SELECT 1 FROM <table> WHERE name = ANY(<tags>) AND ST_DWithin(<geo>, geom::geography, 1, false) LIMIT 1; name列。如果geom属于geom类型,则可以省略强制转换。使用geography进行球体计算,这对于这个短距离来说已经足够了,而且计算起来要快得多。

与一些流逻辑改进一起,您的功能变为:

false

此函数采用一组表名,然后确定所有表是否在指定点的1米范围内具有任何提供的标记至少1个点。这对我来说听起来不太有用。返回一组CREATE OR REPLACE FUNCTION trial(tbl text[], tag text[], geo geography) RETURNS boolean AS $BODY$ DECLARE t text; res int; BEGIN FOREACH t IN ARRAY tbl LOOP EXECUTE 'SELECT 1 FROM ' || quote_ident(t) || ' WHERE name = ANY($1)' || ' AND ST_DWithin($2, geom::geography, 1, false) ' || 'LIMIT 1' INTO res USING tags, geo; IF res IS NULL THEN -- No value was returned so no nearby points RETURN false; END IF; END LOOP; RETURN true; -- If we get here, all tables have at least 1 match END; $BODY$ LANGUAGE plpgsql;,每行给出满足该条件的表的名称,看起来更有用,或者甚至是text版本,为每个表提供数字1米内的点数和该表的匹配标签。