0

这个问题开始,我在 PL/PgSQL 中成功运行了一些动态 SQL EXECUTE,但它似乎没有达到预期的效果。

以下代码是我创建的 plpgsql 函数的一部分。这打算去位于同一轨道上的每个点,并为每个点找到它最近的点,以便最终我将在所有轨道之间创建一个网络。对于某些共振,它无法正常工作。

i 代表当前曲目的编号。

 DECLARE
    _r record;
    i int := 0;
    source_geom character varying;
    target_geom character varying;

BEGIN

WHILE i < 3 --DEPENDS ON THE NUMBER OF TRACKS
LOOP

FOR _r IN EXECUTE ' SELECT a.'|| quote_ident(gid_cname) || ' AS id,'
|| ' st_astext( a.'||quote_ident(geo_cname)||') AS source,' 
|| ' st_astext(b.'||quote_ident(geo_cname)||') AS target, ' 
|| ' ST_Distance(a.'||quote_ident(geo_cname) || ' ,  b.'||quote_ident(geo_cname)||') As dist_ft'
|| ' FROM ' || quote_ident (geom_table) ||' AS a INNER JOIN ' || quote_ident(geom_table) || ' As b ON ST_DWithin(a.'||quote_ident(geo_cname)|| ', b.'||quote_ident(geo_cname)|| ',1000)'
|| ' WHERE b.'||quote_ident(gid_cname)|| ' > a.'||quote_ident(gid_cname)|| ' AND b.'||quote_ident(tid_cname)|| ' = '||i|| 'AND a.'||quote_ident(tid_cname)|| ' = '||i|| 
   ' ORDER BY dist_ft '
|| ' Limit 1 '

LOOP

source_geom := _r.source;
target_geom := _r.target;


EXECUTE 'update ' || quote_ident(geom_table) || 
    ' SET source = ''' || source_geom ||''' 
    , target = ''' || target_geom || ''' 
    WHERE ' || quote_ident(gid_cname) || ' =  ' || _r.id;
END LOOP;

i = i + 1;

END LOOP;

RETURN 'OK';
END;

The thing is that I have tested the query in plain sql and it worked brilliantly. Now for some reason in plpgsql it is not working properly. Below you can find the same query in plain sql.

SELECT a.ogc_fid AS id, st_astext( a.wkb_geometry) AS source, st_astext(b.wkb_geometry) AS target, ST_Distance(a.wkb_geometry, b.wkb_geometry) As dist_ft
FROM track_points AS a INNER JOIN track_points As b
ON ST_DWithin(a.wkb_geometry , b.wkb_geometry, 1000)
WHERE b.ogc_fid > a.ogc_fid AND b.track_fid = 0 AND a.track_fid = 0 
order by dist_ft
4

2 回答 2

1

而不是||quote_literal quote_ident尝试使用format()and EXECUTE ... USING

看到这个最近的答案

当它们在普通 SQL 中工作时,在 PL/PgSQL 中查询失败的常见原因是名称与 PL/PgSQL 中声明的变量发生冲突,但这不适用于动态EXECUTE查询,因为它们不能引用在 PL/PgSQL 函数中声明的变量。

在这种情况下,我认为您在将其转换为动态查询时更有可能出错。

尝试更换:

EXECUTE 'SELECT ...'

和:

query_text = 'SELECT ...'
RAISE NOTICE 'About to run: %',query_text;
EXECUTE query_text;

d如前所述query_text。_ 查看您生成的查询文本是否真的与您手动运行的查询匹配。DECLAREtext

如果格式更好,调试动态 SQL 会容易得多。尝试更多类似的东西:

EXECUTE format(
  $query$
    SELECT a.%1$I AS id,
           st_astext(a.%2$I) AS source,
           st_astext(b.%2$I) AS target,
           ST_Distance(a.%2$I, b.%2$I) AS dist_ft
    FROM %3$I AS a INNER JOIN %3$I As b
      ON ST_DWithin(a.%2$I , b.%2$I, 1000)
    WHERE b.%1$I > a.%1$I 
      AND b.%4$I = 0 AND a.%4$I = 0 
    ORDER BY dist_ft
    LIMIT %5$L
  $query$,
  gid_cname, geo_cname, geom_table, tid_cname, 1
);

不需要USING子句,因为没有传递文字参数。

于 2012-10-22T10:04:43.733 回答
0

我看到了一个非常小的差异: LIMIT 1. 如果你从动态 SQL 中省略它,那会解决它吗?

亲切的问候,

洛克

于 2012-11-02T10:41:33.160 回答