我正在寻求澄清如何确保在一个plpgsql函数中的原子事务,以及在哪里为这个特定的数据库更改设置隔离级别。
在如下所示的plpgsql函数中,我想确保删除和插入都成功。当我试图将它们 Package 在单个事务中时,我得到了一个错误:
ERROR: cannot begin/end transactions in PL/pgSQL
字符串
如果另一个用户添加了默认行为,在执行下面的函数时会发生什么?('RAIN','NIGHT',' 45MPH')* 在 * 此函数删除了自定义行之后,但 * 在 * 它有机会插入自定义行之前?是否有隐式事务 Package 插入和删除,以便在另一个用户更改了功能?我可以设置此功能的隔离级别吗?
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;
型
2条答案
按热度按时间gz5pxeao1#
PL/pgSQL函数在transaction中自动运行,要么全部成功,要么全部失败。请参阅:
如果需要,可以捕获理论上可能发生(但不太可能)的异常。
手册中有关捕获错误的详细信息。
您的功能已审核并简化:
字符串
如果你真的需要像标题中指出的那样 * 开始/结束事务 *,请查看Postgres 11或更高版本(
CREATE PROCEDURE
)中的SQL过程。(但过程目前无法返回集合。)请参阅:此外,您可能希望将
INSERT
和DELETE
替换为“UPSERT”,以安全地处理竞争条件。请参阅:qnyhuwrf2#
更新:在PostgreSQL版本11之后,你可以在存储过程中控制事务。
=在版本10之前:
字符串
“不幸的是,Postgres没有存储过程,所以你总是需要在调用代码中管理事务”- a_horse_with_no_name
Transaction in an exception block - how?