无法从 Postgres plpgsql 过程和异常处理最佳实践中捕获异常?

Cannot catch Exception from Postgres plpgsql Procedure and Exception handling best practices?

我有一个 plpgsql 程序,我只是在其中尝试处理任何可能的异常,因为我将 运行 这些程序 pg_cron(自动)并且我不希望任何事情失败。该过程的基本框架如下所示:

CREATE OR REPLACE PROCEDURE marketing_offers.stackover_overflow_ex_question(limit_size integer)
    LANGUAGE plpgsql
AS
$procedure$
DECLARE
    n_rec_cnt  bigint;
   
BEGIN
        LOOP
            EXIT WHEN n_rec_cnt = 0;
          
           WITH cte AS (SELECT *
                        FROM master_table mt
                        where mt.created_date <= '1999-01-01'::time
                        LIMIT limit_size)
            INSERT INTO some_archive_table (SELECT * FROM cte)
            COMMIT;
           
           GET DIAGNOSTICS n_rec_cnt = row_count;
       
           RAISE EXCEPTION 'Max retry count exceeded';
          
            begin
           EXCEPTION 
           WHEN OTHERS then
            GET STACKED DIAGNOSTICS text_var1 = message_text,
                          text_var2 = PG_EXCEPTION_DETAIL,
                          text_var3 = PG_EXCEPTION_HINT;
            RAISE NOTICE 'error msg is %', text_var1;
              
            UPDATE job_log
            SET error_msg  = text_var1
            return;
           end;
          
           
        END LOOP;      
END;
$procedure$
;

问题是带有 text_var1 的 RAISE NOTICE,它应该包含 SQL 异常消息,但从未被记录,UPDATE 语句对我的 job_log table 也应该保存消息。

我还想补充一点,我不得不用另一个 beginend 包围 EXCEPTION 块,因为如果不这样做,我会得到语法错误.

我只是想从我的 SQL 脚本中捕获异常 - 我应该使用不同的异常类型吗?我应该寻找特定的 SQL 代码吗?我对这里的最佳做法感到困惑

您真的应该开始缩进您的代码。这不仅是为了美观,而且会立即向您显示代码的问题。

正确缩进后的代码如下所示:

BEGIN
   LOOP
      EXIT WHEN n_rec_cnt = 0;

      COMMIT;
           
      RAISE EXCEPTION 'Max retry count exceeded';
          
      begin
      EXCEPTION 
          WHEN OTHERS then
             RAISE NOTICE 'error msg is %', text_var1;
              
             UPDATE job_log
                SET error_msg  = text_var1
                return;
      end;
   END LOOP;      
END;

有两点很明显:

  1. 你忘了前面的分号RETURN→语法错误

  2. EXCEPTION 子句是前一行以 BEGIN 开头的块的一部分。

    由于 EXCEPTION 子句只会捕获在它所属的块中抛出的异常,而该块是空的,执行永远无法到达异常处理程序。

您显然在与 COMMIT 不能在带有 EXCEPTION 子句的块内执行的限制作斗争。但是由于不清楚你要做什么(比如无条件的RAISE EXCEPTION好像没有意义),很难帮到你。