PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Puis-je utiliser des EXCEPTIONS dans une BOUCLE FOR pour forcer la poursuite en cas d'erreur ?

Oui. Vous pouvez placer la charge utile dans un bloc de code séparé avec gestion des exceptions :

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;

Il y a un exemple dans le manuel .

Mais je ne vois pas pourquoi vous attribuez tl2 premier (au lieu de tl1 ), qui est susceptible de provoquer une exception à la première itération de la boucle. Vous pouvez éviter le problème a priori en utilisant un FOR boucle et au lieu d'un curseur explicite en combinaison avec une requête améliorée. Voir ci-dessous.

Aussi, votre UPDATE n'a pas de WHERE condition, qui est presque certainement erronée.

Et la fonction pgr_trsp() semble pour le moins suspect. Passer du code sous forme de texte pue l'injection SQL. Cette réponse connexe sur dba.SE a une évaluation de SQLi dans plpgsql :
Fonctions Postgres vs requêtes préparées

Fonction auditée dans la question mise à jour

Réécrire votre code pour utiliser une logique basée sur des ensembles au lieu d'une boucle peut être plus propre et plus rapide. Pour commencer, vous pouvez simplifier quelque chose comme ceci (toujours avec une boucle, mais simplifiée) :

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 particulier, en utilisant ...