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;

問題は、プレーン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
4

2 に答える 2

1

ではなく||quote_literal quote_identとを使用してみてformat()くださいEXECUTE ... USING

この最近の回答を参照してください。

プレーンSQLで動作するときにPL/PgSQLで失敗するクエリの通常の原因は、PL / PgSQLで宣言された変数との名前の衝突ですが、PL / PgSQL関数でEXECUTE宣言された変数を参照できないため、動的クエリには当てはまりません。

この場合、動的クエリに変換するときに間違いを犯した可能性が高いと思います。

交換してみてください:

EXECUTE 'SELECT ...'

と:

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

ここquery_textで、 DECLAREdはtext前述のとおりです。生成しているクエリテキストが、手動で実行したクエリと実際に一致するかどうかを確認します。

フォーマットが適切であれば、動的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 に答える