Ja. U kunt de payload in een apart codeblok plaatsen met uitzonderingsafhandeling:
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;
Er is een voorbeeld in de handleiding .
Maar ik begrijp niet waarom je tl2
. toewijst eerst (in plaats van tl1
), die ongetwijfeld een uitzondering zal veroorzaken bij de eerste iteratie van de lus. U kunt het probleem a priori vermijden door een FOR
lus
en in plaats van een expliciete cursor in combinatie met een uitgebreide zoekopdracht. Zie hieronder.
Ook uw UPDATE
heeft geen WHERE
staat, wat vrijwel zeker verkeerd is.
En de functie pgr_trsp()
ziet er op zijn zachtst gezegd verdacht uit. Code doorgeven als tekst ruikt naar SQL-injectie. Dit gerelateerde antwoord op dba.SE heeft een beoordeling van SQLi in plpgsql:
Postgres-functies versus voorbereide query's
Gecontroleerde functie in bijgewerkte vraag
Het herschrijven van uw code om op set gebaseerde logica te gebruiken in plaats van lussen kan schoner en sneller zijn. Om te beginnen kunt u dit vereenvoudigen tot iets als dit (nog steeds met een lus, maar vereenvoudigd):
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;
In het bijzonder, met behulp van ...
- Een
FOR
lus met impliciete cursor in plaats van een (onhandige) expliciete cursor. - Vensterfuncties.