我可以在FOR LOOP中使用EXCEPTIONs强制错误继续吗?

Pet*_*sos 0 postgresql loops exception-handling plpgsql

发生(可预测或不可预测)错误时,是否可以在FOR循环中使用EXCEPTIONs强制继续执行?这是一个片段:

FOR temp_rec IN tlcursor LOOP
  tl2 := temp_rec; --the location to be updated
  --Do the Routing and UPDATE the taxilocs row.
  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);
  tl1 := tl2;
END LOOP;
Run Code Online (Sandbox Code Playgroud)

一个例子是,在第一次迭代期间,tl1未分配。另一个可能是该函数pge_trsp()没有提供结果。如果在执行过程中发生任何这种情况,是否可以强制循环继续?
更新!!
这是我最新的代码:

CREATE OR REPLACE FUNCTION fm_seqrouting() RETURNS integer AS $$
--Declarations
DECLARE 
    tlcursor SCROLL CURSOR FOR SELECT 
        oid,
        veh_id,
        date_time AS dt,
        th_2po_4pgr_id AS map_id,
        th_2po_4pgr_position AS map_pos FROM testlocs
        ORDER BY veh_id, dt;
    tl1 RECORD;
    tl2 RECORD;
    i integer;
BEGIN
--CODE to calculate routes and update table
    i := 0;
    FOR temp_rec IN tlcursor LOOP
        tl2 := temp_rec; --the location to be updated
        BEGIN --Nest the UPDATE in a block to esace errors
        --Do the Routing and UPDATE the taxilocs row.
        UPDATE taxilocs20120113 
            SET "pgRoute" = pgr_trsp (
                'SELECT * FROM th_2po_4pgr',
                tl1.map_id, tl1.map_pos, tl2.map_id, tl2.map_pos, false, true)
        WHERE taxilocs20120113.oid = tl2.oid;
        i := i + 1;
        EXCEPTION
            WHEN SQLSTATE '55000' THEN NULL;
            WHEN SQLSTATE 'XX000' THEN NULL;
            WHEN SQLSTATE '38001' THEN NULL;
        END;
        tl1 := tl2;
    END LOOP;
RETURN i;
END;
$$ LANGUAGE plpgsql;  
Run Code Online (Sandbox Code Playgroud)

事实是,这在内存方面非常紧张,但是我是编程新手(我什至都​​不是程序员)。任何提示表示赞赏!

Erw*_*ter 5

是。您可以将有效负载放在带有异常处理的单独代码块中:

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;
Run Code Online (Sandbox Code Playgroud)

手册中有一个示例

但是我看不到为什么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;
Run Code Online (Sandbox Code Playgroud)

特别是使用...