прервать всю транзакцию, когда в postgresql произошла ошибка одной функции - PullRequest
0 голосов
/ 30 октября 2019

У меня есть основная функция для вызова каждой дочерней функции. Я хочу откат функции, если одна из дочерних функций выдает ошибку. Основная функция работает нормально, если что-то пойдет не так, и транзакция будет остановлена, но сообщение об ошибке не появилось в таблице ошибок. Я хочу, чтобы с дочерней функцией что-то пошло не так, мне все равно, что транзакция основной функции остановится и откатится, а все остальные успешные дочерние функции не будут выполнены.

вот мой скрипт:

CREATE OR REPLACE FUNCTION ecisdrdm.pr_merge_staging_tables(    OUT v_ret text)
    RETURNS text
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE  AS $BODY$

DECLARE

    v_errorcode      text;   v_errormsg       varchar(512);    v_module         varchar(32) = 'pr_merge_staging_tables';    v_host          varchar(32) = inet_server_addr();

begin

    PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Starting MERGE Process' );       begin   v_ret = '0';

    if v_ret = '0' then            ---     --- Perform the merge on APPLICATION_CDIM    ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_APPLICATION_CDIM' );
                PERFORM ecisdrdm.pr_mig_stg_application_cdim();         -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_APPLICATION_CDIM' );
            end if;


    ---  2. STG_BNFT_CURR_FACT  ----
        if v_ret = '0' then

    ---     --- Perform the merge on BNFT_CURR_FACT     ---

        PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_BNFT_CURR_FACT' );
                PERFORM ecisdrdm.pr_mig_stg_bnft_curr_fact();       -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION

        PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_BNFT_CURR_FACT' );
            end if;


    ----    --  3. STG_BNFT_FACT    ----
        if v_ret = '0' then     ---     --- Perform the merge on BNFT_FACT  ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_BNFT_FACT' );
                PERFORM ecisdrdm.pr_mig_stg_bnft_fact();        -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION        v_ret = '0';
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_BNFT_FACT' );       end if;


    ----    --  4. STG_BNFT_HIST_ACTN_LDIM  ----
        if v_ret = '0' then     ---     --- Perform the merge on BNFT_HIST_ACTN_LDIM    ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_BNFT_HIST_ACTN_LDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_bnft_hist_actn_ldim ();         -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_BNFT_HIST_ACTN_LDIM ' );

    end if;


    ----    --  5. STG_CNTRY_ST_CDIM    ----
        if v_ret = '0' then     ---     --- Perform the merge on CNTRY_ST_CDIM  ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Started merging STG_CNTRY_ST_CDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_cntry_st_cdim();        -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_CNTRY_ST_CDIM ');       end if;


    ----    --  6. STG_FRM_CDIM     ----
        if v_ret = '0' then     ---     --- Perform the merge on FRM_CDIM   ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_FRM_CDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_frm_cdim();         -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                        PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_FRM_CDIM ' );       end if;


    ----    --  7. STG_G28  ----
        if v_ret = '0' then     ---     --- Perform the merge on G28    ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Started merging STG_G28 ' );
                PERFORM ecisdrdm.pr_mig_stg_g28();      -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_G28 ' );        end if;


    ----    --  8. STG_PRTY_CDIM    ----
        if v_ret = '0' then     ---     --- Perform the merge on PRTY_CDIM  ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_PRTY_CDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_prty_cdim();        -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_PRTY_CDIM ' );      end if;


    ----    --  9. STG_PRTY_TYP_LKUP    ----
        if v_ret = '0' then     ---     --- Perform the merge on PRTY_TYP_LKUP  ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_PRTY_TYP_LKUP ' );
                PERFORM ecisdrdm.pr_mig_stg_prty_typ_lkup();        -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Finished merging STG_ PRTY_TYP_LKUP ' );      end if;

    ----    --  10. STG_R2I864  ----
        if v_ret = '0' then     ---     --- Perform the merge on R2I864     ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_R2I864 ' );
                PERFORM ecisdrdm.pr_mig_stg_r2i864();       -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished merging STG_R2I864 ' );         end if;

    ----    --  11. STG_REMIT   ----
        if v_ret = '0' then     ---     --- Perform the merge on REMIT  ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_REMIT ' );
                PERFORM ecisdrdm.pr_mig_stg_remit();        -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Finished merging STG_ REMIT ' );      end if;

    ----    --  12. STG_SRC_SYS_CDIM    ----
        if v_ret = '0' then     ---     --- Perform the merge on SRC_SYS_CDIM   ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Started merging STG_SRC_SYS_CDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_src_sys_cdim();         -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0',  'Finished merging STG_SRC_SYS_CDIM ' );      end if;


    ----    --  13. STG_SVC_CTR_CDIM    ----
        if v_ret = '0' then     ---     --- Perform the merge on SVC_CTR_CDIM   ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Started merging STG_SVC_CTR_CDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_svc_ctr_cdim();         -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Finished merging STG_SVC_CTR_CDIM ' );        end if;


    ----    --  14. STG_USCIS_EMP_CDIM  ----
        if v_ret = '0' then     ---     --- Perform the merge on USCIS_EMP_CDIM     ---
            PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Started merging STG_USCIS_EMP_CDIM ' );
                PERFORM ecisdrdm.pr_mig_stg_uscis_emp_cdim_cd ();       -- TODO: INVESTIGATE HOW TO RECEIVE THE OUT PARAMETER RETRUNED FROM FUNCTION
                PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0','Finished merging STG_USCIS_EMP_CDIM ' );      end if;


---
--- This does the final commit or rollback for the entire merge process.
---

    if v_errorcode = '0' then       PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished MERGE PROCESS - COMMIT WORK' );         /*  commit work; */     else        PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, '0', 'Finished MERGE PROCESS - ROLLBACK WORK ' );      /*  rollback work; */       ROLLBACK;       end if;

----
--- Exception error handler
----

exception    when others then
        v_errorcode := SQLSTATE;
        v_errormsg  := SQLERRM;         v_ret       := v_errorcode;

    PERFORM ecisdrdm.pr_write_error_log( CURRENT_USER, v_host, v_module, v_errorcode, v_errormsg);   end;

END; $BODY$;

введите описание изображения здесь

Я хочу получить уведомление Нарушено то, что произошло на уровне приложения, запишите в таблицу ошибок и выполните откат независимо от того, какая функцияпотерпеть неудачу, не просто продолжая функцию транзакции.

1 Ответ

1 голос
/ 30 октября 2019

Из вашего каскада слов я предполагаю, что вы хотите отменить все, что произошло в функции, и записать сообщение об ошибке. Это будет работать следующим образом:

BEGIN
   PERFORM function1();
   PERFORM function2();
   /* more work */
EXCEPTION
   WHEN OTHERS THEN
      INSERT INTO log_table VALUES (...);
END;

Все, что находится между BEGIN и EXCEPTION, будет выполняться в субтранзакции. Если выдается какое-либо исключение, вся субтранзакция откатывается и регистрируется ошибка.

...