Sql Firebird 2.5在循环中提交/回滚(使用自治事务)
我必须处理存储过程循环中的记录,例如:Sql Firebird 2.5在循环中提交/回滚(使用自治事务),sql,firebird,firebird-psql,Sql,Firebird,Firebird Psql,我必须处理存储过程循环中的记录,例如: create or alter procedure process_waiting_records as declare v_id type of column my_table.id; begin for select t.id from my_table t where (t.status = 'WAITING_TO_PROCESS') ord
create or alter procedure process_waiting_records
as
declare v_id type of column my_table.id;
begin
for
select
t.id
from
my_table t
where
(t.status = 'WAITING_TO_PROCESS')
order by
t.created_at
into
:v_id
do
begin
execute procedure process_one_record(:v_id);
end
end ^
问题是当执行process\u one\u record()
失败(生成任何类型的异常)时,整个修改集将从调用代码回滚
我们的目标是处理所有可能的记录,此时我并不关心某些记录是否无法处理,这些失败的记录将被记录在日志表中(使用自治事务)
我正考虑在一个自治事务块中调用process\u one\u record()
存储过程,同时使用when any do(伪代码)
子句。但是,我认为这是行不通的,因为失败的事务将不会回滚,而是提交(参考此主题:)
有人能告诉我解决这个问题的正确方向吗?你不需要匿名交易。当从存储过程中抛出异常时,该存储过程的效果将自动撤消。如果存储过程包含
SUSPEND
,则仅撤消上次SUSPEND
之前的效果(将其视为保存点)。对于任何其他形式的回滚,都需要显式回滚事务
另请参见Firebird 2.5语言参考中的
在PSQL中不允许使用事务控制语句,这将
中断调用过程的语句的原子性。
但是,Firebird确实支持异常的引发和处理
在PSQL中,以便在存储过程和触发器中执行操作
可以有选择地撤消,而不会使整个过程失败
在内部,自动保存点用于:
- 撤消出现异常的
块中的所有操作BEGIN…END
- 撤消程序或触发器执行的所有操作,或者对于可选程序,撤消自上次挂起以来执行的所有操作, 当执行因未捕获的错误或错误而提前终止时 例外情况
BEGIN…END
块本身不会创建自动
保存点。保存点仅在包含WHEN的块中创建
用于处理异常的语句
在这种情况下,由于需要撤消单个进程\单\记录
的影响,而不是进程\等待\记录
中的整个处理,因此您需要允许从进程\单\记录
中抛出异常,但为该单个过程调用捕获它
简而言之,您需要执行以下操作:
for select
...
do
begin
execute procedure process_one_record(:v_id);
when any do
begin
-- do nothing, last call to `process_one_record` was undone
end
end
因此,如果我正确理解您使用这种方法所做的所有由失败的进程\u one\u record()所做的更改都将自动回滚(根本不涉及挂起),但是以前成功的进程\u one\u record()调用仍然可以在进程结束时提交\u waiting\u records?@tcxbalage Yes,只有对
process\u one\u record
的失败调用中的工作被撤消,其余工作被保留并可以提交。请注意,您实际上也可以在进程\u one_记录
中捕获异常,在块中捕获异常会触发该块中所做工作的回滚,但是让异常从存储过程中出来并在调用方中处理它更干净。我完全没有注意到这一点“Savepoints and PSQL”lang.ref.我一直在寻找的是异常处理。我应该更彻底地做我的研究。谢谢你的帮助!