sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Puedo usar EXCEPCIONES en un FOR LOOP para forzar la continuación en caso de error?

Sí. Puede colocar la carga útil en un bloque de código separado con manejo de excepciones:

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;

Hay un ejemplo en el manual .

Pero no veo por qué asignas tl2 primero (en lugar de tl1 ), que está obligado a causar una excepción en la primera iteración del bucle. Puede evitar el problema a priori usando un FOR bucle y en lugar de un cursor explícito en combinación con una consulta mejorada. Ver más abajo.

Además, su UPDATE no tiene WHERE condición, que es casi seguro que es incorrecta.

Y la función pgr_trsp() parece sospechoso por decir lo menos. Pasar código como texto huele a inyección SQL. Esta respuesta relacionada en dba.SE tiene una evaluación de SQLi en plpgsql:
Funciones de Postgres frente a consultas preparadas

Función auditada en pregunta actualizada

Reescribir su código para usar lógica basada en conjuntos en lugar de bucles podría ser más limpio y rápido. Para empezar, puede simplificar a algo como esto (todavía con un bucle, pero simplificado):

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;

En particular, usando...