PostgreSQL的不能在PL / pgSQL的开始/结束交易(PostgreSQL cannot

2019-08-08 11:48发布

我正在寻求澄清如何确保在PLPGSQL功能的原子事务,并在隔离级别设置为这个特殊的变化到数据库。

在下面显示的PLPGSQL功能,我要确保,无论是删除和插入成功。 我得到一个错误,当我尝试将它们包装在一个单独的事务:
ERROR: cannot begin/end transactions in PL/pgSQL

如果另一个用户已增加了对环境默认行为(“RAIN”,“夜景”,“45英里每小时”) 后,此功能已删除的自定义行下面的函数的执行过程中会发生什么,但之前有机会插入自定义行? 是否有一个隐含的交易包裹的插入和删除,使两者都回滚如果另一个用户已更改:该函数引用的行吗? 我可以设置此功能的隔离级别?

create function foo(v_weather varchar(10), v_timeofday varchar(10), v_speed varchar(10),
   v_behavior varchar(10))
   returns setof CUSTOMBEHAVIOR
   as $body$
   begin

      -- run-time error if either of these lines is un-commented

      -- start transaction ISOLATION LEVEL READ COMMITTED;
      -- or, alternatively, set transaction ISOLATION LEVEL READ COMMITTED;


      delete from CUSTOMBEHAVIOR 
      where weather = 'RAIN' and timeofday = 'NIGHT' and speed= '45MPH' ;

      -- if there is no default behavior insert a custom behavior

      if not exists
        (select id from DEFAULTBEHAVIOR where a = 'RAIN' and b = 'NIGHT' and c= '45MPH') then
         insert into CUSTOMBEHAVIOR
           (weather, timeofday, speed, behavior)
         values
           (v_weather, v_timeofday, v_speed, v_behavior);
      end if;

      return QUERY
      select * from CUSTOMBEHAVIOR where ...   ;

      -- commit;

   end
   $body$  LANGUAGE plpgsql;

Answer 1:

一个PLPGSQL功能的事务中自动运行。 这一切都成功或者失败的所有。 手动:

函数和触发器过程总是在一个由外层查询建立起来的事务中执行-他们不能开始或者提交该事务,因为不会有什么背景让他们在执行然而,包含块EXCEPTION有效条款形成一个子事务,可以回滚,而不会影响外部事务。 欲了解更多有关见第42.6.6。

所以,如果你需要,你能赶上在理论上可能发生(但不太可能)一个例外。
在手册中捕获错误的详细信息。

你的功能审查,并简化为:

CREATE FUNCTION foo(v_weather text
                  , v_timeofday text
                  , v_speed text
                  , v_behavior text)
  RETURNS SETOF custombehavior AS
$func$
BEGIN

DELETE FROM custombehavior
WHERE  weather = 'RAIN'
AND    timeofday = 'NIGHT'
AND    speed = '45MPH';

INSERT INTO custombehavior (weather, timeofday, speed, behavior)
SELECT v_weather, v_timeofday, v_speed, v_behavior
WHERE  NOT EXISTS (
   SELECT FROM defaultbehavior
   WHERE  a = 'RAIN'
   AND    b = 'NIGHT'
   AND    c = '45MPH'
   );

RETURN QUERY
SELECT * FROM custombehavior WHERE ... ;

END
$func$  LANGUAGE plpgsql;

如果你确实需要开始/结束交易像标题所示看看SQL程序Postgres的11或更高版本( CREATE PROCEDURE )。 有关:

  • 在PostgreSQL,就是什么是“存储过程”和其他类型的功能区别?


Answer 2:

START TRANSACTION;
select foo() ;
COMMIT;

“不幸的是Postgres有没有存储的过程,所以你总是需要调用代码来管理事务” - a_horse_with_no_name

交易中的异常块-怎么样?



文章来源: PostgreSQL cannot begin/end transactions in PL/pgSQL