路由网络功能问题

时间:2012-10-22 09:10:18

标签: sql sql-server postgresql plpgsql

this question开始,我有一些动态SQL我在PL / PgSQL中使用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;

问题是我在普通的sql中测试了查询,并且它运行得非常出色。现在由于某种原因在plpgsql中它无法正常工作。下面你可以在普通的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

2 个答案:

答案 0 :(得分:1)

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

请参阅this recent answer

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

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

尝试更换:

EXECUTE 'SELECT ...'

使用:

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

其中query_text DECLARE d为text之前的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 ); 。查看您正在生成的查询文本是否与您手动运行的查询相匹配。

如果格式化得更好,调试动态SQL要容易得多。尝试更像:

USING

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

答案 1 :(得分:0)

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

亲切的问候,

Loek