为什么我无法将事务回滚到 plpgsql 存储过程中的特定保存点

问题描述 投票:0回答:1

我在 pgadmin 上的“回滚到保存点”中的“To”处执行存储过程时遇到错误。

CREATE OR REPLACE PROCEDURE demo8()
AS $$
BEGIN
   INSERT INTO statefis VALUES(83, 'Maharashtra');

   SAVEPOINT abc;

   INSERT INTO statefis VALUES (52, KERLA);
   ROLLBACK TO SAVEPOINT abc;

   INSERT INTO statefis VALUES(35, DELHI); 
   RELEASE SAVEPOINT abc;
   COMMIT;

   RAISE NOTICE Transaction commited succesfully':
END;
$$ LANGUAGE plpgsql;
postgresql stored-procedures plpgsql rollback pgadmin-4
1个回答
0
投票

您不能直接在 PL/pgSQL 中使用保存点。相反,您可以使用

BEGIN
处理程序编写
END
/
EXCEPTION
块。在底层,这是通过子事务实现的,就像保存点一样。

您的代码将如下所示(包括一些基本语法修复):

CREATE OR REPLACE PROCEDURE demo8()
AS $$
BEGIN
   INSERT INTO statefis VALUES(83, 'Maharashtra');

   /*
    * This sets a savepoint, since there is an EXCEPTION clause.
    * If the INSERT doesn't throw an exception, the subtransaction
    * will get "subcommitted" when execution leaves the block.
    * This is just the same as releasing the savepoint.
    * If PostgreSQL enters the exception handler, the subtransaction
    * will be rolled back.
    */
   BEGIN
      INSERT INTO statefis VALUES (52, 'KERLA');
   EXCEPTION
      /* you could capture any other exception as well */
      WHEN unique_violation THEN
         /*
          * As soon as PostgreSQL enters the exception handler,
          * it rolls back the subtransaction.
          * Since that's all you want to happen, add a statement
          * that does nothing.
          */
         NULL;
   END;

   INSERT INTO statefis VALUES(35, 'DELHI'); 

   /*
    * There is little point in this COMMIT.
    * PostgreSQL will commit anyway as soon as the procedure is done.
    */
   COMMIT;

   RAISE NOTICE 'Transaction committed successfully':
END;
$$ LANGUAGE plpgsql;
© www.soinside.com 2019 - 2024. All rights reserved.