从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
答案 0 :(得分:1)
而不是||
,quote_literal
quote_ident
尝试使用format()
和EXECUTE ... USING
。
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