Postgresql

“TO”處或附近的 ROLLBACK TO SAVEPOINT 語法錯誤

  • March 25, 2020

我在 PostgreSQL 中執行以下 FUNCTION 時遇到問題

CREATE OR REPLACE FUNCTION pckg_fcvoi.supprimer_voies_plus_42c (CodeEntite text) RETURNS VOID AS $body$
DECLARE

   cpt_voies_ACTIV  numeric := 0;
   cpt_voies_User   numeric := 0;
   cpt_voies_42C    numeric := 0;
   cpt_voies_sup    numeric := 0;
   /*----------------------------------------------------------------*/
   /* Liste des voies non importees de 42C, susceptibles d'etre      */
   /* supprimees.                                                    */
   /*----------------------------------------------------------------*/
   cursor_VOIES_PLUS_42C CURSOR FOR
     SELECT com_commune.cod_ent,
            com_voie.cod_insee,
            com_voie.cod_rivoli,
            com_voie.lib
       FROM com_voie,
            com_commune
      WHERE com_commune.cod_insee = com_voie.cod_insee
        AND com_commune.cod_ent   = CodeEntite
        AND com_voie.origine_voie = 'D';

BEGIN
   -- DBMS_OUTPUT.ENABLE(1000000);

   SELECT COUNT(*) INTO STRICT cpt_voies_ACTIV
     FROM com_voie,
          com_commune
    WHERE com_commune.cod_insee = com_voie.cod_insee
      AND com_commune.cod_ent = CodeEntite;
   SELECT COUNT(*) INTO STRICT cpt_voies_User
     FROM com_voie,
          com_commune
    WHERE com_commune.cod_insee = com_voie.cod_insee
      AND com_commune.cod_ent = CodeEntite
      and com_voie.origine_voie = 'U';
   SELECT COUNT(*) INTO STRICT cpt_voies_42C
     FROM com_voie,
          com_commune
    WHERE com_commune.cod_insee = com_voie.cod_insee
      AND com_commune.cod_ent = CodeEntite
      and com_voie.origine_voie = 'S';
   SELECT COUNT(*) INTO STRICT cpt_voies_sup
     FROM com_voie,
          com_commune
    WHERE com_commune.cod_insee = com_voie.cod_insee
      AND com_commune.cod_ent = CodeEntite
      and com_voie.origine_voie = 'D';

   RAISE NOTICE '  - Nombre de voies dans la base ACTIV pour % : %', CodeEntite, cpt_voies_ACTIV;
   RAISE NOTICE '  - Nombre de voies utilisateur        pour % : %', CodeEntite, cpt_voies_User;
   RAISE NOTICE '  - Nombre de voies importees de 42C   pour % : %', CodeEntite, cpt_voies_42C;
   RAISE NOTICE '  - Nombre de voies supprimables       pour % : %', CodeEntite, cpt_voies_sup;

   /*---------------------------------------------------------------------------------------*/
   /* Pour toutes les voies susceptibles d'etre supprimees                                  */
   /* dont le cod_ent est a traiter :                                                       */
   /* - Supprimer la voie                                                                   */
   /* - si la suppression echoue                                                            */
   /*   alors                                                                               */
   /*     afficher la voie est supprimable mais dossier attache                             */
   /*   sinon                                                                               */
   /*     afficher la voie est supprimee                                                    */
   /*   finsi                                                                               */
   /*---------------------------------------------------------------------------------------*/
   RAISE NOTICE 'Voies ne pouvant etre supprimees de la base ACTIV pour % :', CodeEntite;
   RAISE NOTICE '---------------------------------------------------------';
   cpt_voies_sup := 0;
   FOR enreg_VOIES_PLUS_42C IN cursor_VOIES_PLUS_42C LOOP
     BEGIN
       DELETE FROM com_voie
        WHERE cod_insee  = enreg_VOIES_PLUS_42C.cod_insee
          AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
/*        DBMS_OUTPUT.PUT_LINE('Suppression de '||enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB);*/
       cpt_voies_sup := cpt_voies_sup + 1;
     EXCEPTION
       /*-----------------------------------------------------------*/
       /* La suppression de la voie a echoue                        */
       /*-----------------------------------------------------------*/
       WHEN OTHERS THEN
         IF position('ACTIV.FK_CORRESP_VOIE' in SQLERRM) > 0
         THEN
           /*-------------------------------------------------------------*/
           /* La suppression de la voie a echoue :                        */
           /* supprimer la correspondance voie-gestionnaire, puis la voie */
           /*-------------------------------------------------------------*/
           BEGIN
/*              DBMS_OUTPUT.PUT_LINE(enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB||'; Declaree dans SAV_CORRESP_VOIE_GEST');*/
             SAVEPOINT SP_FK_CORRESP_VOIE;
             DELETE FROM sav_corresp_voie_gest
              WHERE cod_insee  = enreg_VOIES_PLUS_42C.cod_insee
                AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
             DELETE FROM com_voie
              WHERE cod_insee  = enreg_VOIES_PLUS_42C.cod_insee
                AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
/*              DBMS_OUTPUT.PUT_LINE('Suppression de '||enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB);*/
             cpt_voies_sup := cpt_voies_sup + 1;
           EXCEPTION
             WHEN OTHERS THEN
               ROLLBACK TO SAVEPOINT SP_FK_CORRESP_VOIE;
           END;
         ELSE
           /*-----------------------------------------------------------*/
           /* La suppression de la voie a echoue : afficher la cause    */
           /*-----------------------------------------------------------*/
           RAISE NOTICE '%;%;%;%;%', enreg_VOIES_PLUS_42C.COD_ENT, enreg_VOIES_PLUS_42C.COD_INSEE, enreg_VOIES_PLUS_42C.COD_RIVOLI, enreg_VOIES_PLUS_42C.LIB, SUBSTR(SQLERRM, 1, 200);
         END IF;
     END;
   END LOOP;
   RAISE NOTICE '  - Nombre de voies supprimees         pour % : %', CodeEntite, cpt_voies_sup;

 EXCEPTION
   WHEN OTHERS THEN
     RAISE NOTICE 'Exception dans pckg_fcvoi.supprimer_voies_plus_42c(%) : %, %', CodeEntite, SQLSTATE, SUBSTR(SQLERRM, 1, 100);
     RAISE NOTICE 'ARRET DU TRAITEMENT !';
     ROLLBACK;
 END;

我有這個錯誤

“TO”處或附近的語法錯誤。

它與異常塊有關嗎?

有什麼解決辦法嗎?

剛發現這個:

在 PL/pgSQL 中,當一個異常被 EXCEPTION 子句擷取時,自塊的 BEGIN 以來的所有數據庫更改都會自動回滾。如果您正在翻譯一個以這種風格使用 SAVEPOINT 和 ROLLBACK TO 的 Oracle 過程,您的任務很簡單:只需省略 SAVEPOINT 和 ROLLBACK TO

來源:https ://www.postgresql.org/docs/10/plpgsql-porting.html 。

它看起來像 PL/pgSQL 語法限制:您可以創建保存點,但不能使用“ROLLBACK TO保存點”語句。我沒有在文件中找到這個限制,儘管文件說不能在異常塊中執行 ROLLBACK:

引用自:https://dba.stackexchange.com/questions/262528