我有一个目前在 Oracle Database 19C 中看起来像这样的过程
Declare
i integer;
BEGIN
Delete from t_invent;
-- If I add commit here or remove the delete statement here then the error wouldnt occurred.
FOR r_in IN (SELECT * FROM t_in) LOOP
-- Insert into another table
INSERT INTO t_invent (item_id, item_name) VALUES (r_in.item_id, r_in.item_name);
-- Rollback the transaction
if r_in.count = 90 then
ROLLBACK;
-- Rollback here would cauase the procedure show this error ORA-01002: Fetch out of Sequence.
end if;
END LOOP;
END;
根据我的进一步测试,我发现如果我在 for 循环之前添加 Commit,则在这种情况下不会出现获取乱序问题下方的回滚。
另一方面,我在这个问题上添加了dbms_output.put_line来跟踪,我发现回滚不会直接让整个for循环崩溃,有时它可以继续循环12个数据然后它会崩溃。
基于此错误的 Oracle 文档 - ORA-01002:Fetch out of Sequence。 https://docs.oracle.com/en/error-help/db/ora-01002/?r=19c 它表明游标无效会让Oracle显示此错误。
此外,在 for 循环中添加提交(例如大约 50 个数据,然后提交)可以解决此问题,但如果我增加到 100 个数据,则错误将再次显示。
看来回滚和提交会对游标产生影响。
我怀疑for循环中的回滚会回滚事务以及上面的删除语句。但是我不知道为什么游标无效,因为我没有在此表上执行任何 DML (t_in)
以前有人遇到过这个问题吗?有人对这种行为有任何想法吗?
您可以抛出异常并在捕获异常时回滚,而不是尝试在循环内回滚:
DECLARE
needs_rollback EXCEPTION;
PRAGMA EXCEPTION_INIT(needs_rollback, -20001);
BEGIN
Delete from t_invent;
FOR r_in IN (SELECT * FROM t_in) LOOP
-- Insert into another table
INSERT INTO t_invent (item_id, item_name) VALUES (r_in.item_id, r_in.item_name);
-- Rollback the transaction
if r_in.count = 90 then
--ROLLBACK;
raise needs_rollback;
end if;
END LOOP;
EXCEPTION
WHEN needs_rollback THEN
rollback;
END;