はい。ペイロードは、例外処理を使用して別のコードブロックに入れることができます:
FOR temp_rec IN tlcursor LOOP
tl2 := temp_rec; --the location to be updated
--Do the Routing and UPDATE the taxilocs row.
BEGIN
UPDATE taxilocs20120113
SET route = pgr_trsp (
'SELECT * FROM th_2po_4pgr',
tl1.map_id, tl1.map_pos, tl2.map_id, tl2.map_pos, false, true);
EXCEPTION WHEN OTHERS THEN
-- keep looping
END;
tl1 := tl2;
END LOOP;
マニュアルには、例があります。 。
しかし、なぜtl2
を割り当てるのかわかりません。 最初に(tl1
の代わりに )、これはループの最初の反復で例外を引き起こすようにバインドされています。 FOR
ループ
拡張クエリと組み合わせた明示カーソルの代わりに。以下を参照してください。
また、UPDATE
WHERE
はありません 状態、これはほぼ間違いなく間違っています。
そして、関数pgr_trsp()
控えめに言っても疑わしいようです。 SQLインジェクションのテキストリークとしてコードを渡す。 dba.SEに関するこの関連する回答には、plpgsqlのSQLiの評価があります。
Postgres関数と準備されたクエリ
更新された質問で監査された機能
ループの代わりにセットベースのロジックを使用するようにコードを書き直すと、よりクリーンで高速になる可能性があります。まず、次のように簡略化できます(ループはありますが、簡略化されています):
CREATE OR REPLACE FUNCTION fm_seqrouting()
RETURNS integer AS
$func$
DECLARE
r record;
BEGIN
FOR r IN
SELECT oid -- no proper pk?
,th_2po_4pgr_id AS map_id1
,th_2po_4pgr_position AS map_pos1
,lead(th_2po_4pgr_id) OVER w AS map_id2
,lead(th_2po_4pgr_position) OVER w AS map_pos2
,count(*) OVER () AS ct
FROM testlocs
WINDOW w AS (ORDER BY veh_id, dt)
ORDER BY veh_id, dt -- you don't need order by columns in result
LOOP
BEGIN -- may be unnecessary
UPDATE taxilocs20120113
SET "pgRoute" = pgr_trsp(
'SELECT * FROM th_2po_4pgr'
,r.last_map_id, r.last_map_pos, r.map_id, r.map_pos, false, true)
WHERE taxilocs20120113.oid = r.oid;
EXCEPTION
WHEN SQLSTATE '55000' THEN NULL;
WHEN SQLSTATE 'XX000' THEN NULL;
WHEN SQLSTATE '38001' THEN NULL;
END;
END LOOP;
RETURN r.ct;
END
$func$ LANGUAGE plpgsql;
特に、...
を使用する-
FOR
暗黙カーソルでループする (扱いにくい)明示的なカーソルの代わりに。 - ウィンドウ関数。