【问题标题】:Cannot catch Exception from Postgres plpgsql Procedure and Exception handling best practices?无法从 Postgres plpgsql 过程和异常处理最佳实践中捕获异常?
【发布时间】:2021-10-09 04:39:45
【问题描述】:

我有一个 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 异常消息,从不会被记录到我的 job_log 表中应该保存该消息的 UPDATE 语句也。

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

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

【问题讨论】:

    标签: postgresql exception stored-procedures plpgsql


    【解决方案1】:

    您应该真正开始缩进您的代码。这不仅仅是为了漂亮,而是会立即向您展示您的代码存在的问题。

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

    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似乎没有意义),所以很难帮你。

    【讨论】:

    • 最佳答案谢谢
    猜你喜欢
    • 2018-01-03
    • 1970-01-01
    • 2017-05-11
    • 2013-05-09
    • 2011-11-10
    • 1970-01-01
    • 2013-04-22
    相关资源
    最近更新 更多