В рабочем проекте начала появляться ошибка "ORA-1002 Fetch out of sequence". Продебажил и заметил что ошибка появляется в неявном курсоре на следующей итерации. До самого курсора есть еще куча DML, после какого-то стоит Commit, после какого-то нет.
Смысл курсора такой: идет выгрузка документов в центральную базу с обновлением признака выгрузки. Вся внутренность цикла завернута в exception:
exception
when others then
v_st := SQLERRM;
rollback;
dbms_output.put_line(v_st);
end;
После первой неудачной итерации вижу как дебагер переходит на for s in (select... и выпадает ошибка ORA-1002 Fetch out of sequence
В итоге пришлось поставить Commit перед циклом и все заработало.
Поискал в интернете и нашел статью
Провел свои эксперименты. Первоначально создал две таблички tbl_1 и tbl_2 с одним числовым полем id1 и id2 соответственно. В Test Windows в PL/SQL Developer попытался выполнить такой код:
И после первой итерации получаем "ORA-01002 Fetch out of sequence", а в DBMS Output только одну запись: ORA-01476: divisor is equal to zero.
Меняем код - добавляем Commit перед циклом и все отрабатывает без ошибок. На выходе 2 записи:
ORA-01476: divisor is equal to zero
ORA-01476: divisor is equal to zero
Пробуем использовать Savepoint:
На выходе получаем 2 записи:
ORA-01476: divisor is equal to zero => 1
ORA-01476: divisor is equal to zero => 2
Вольный перевод причины возникновения ошибки: Rollback возвращает нас к состоянию до открытия курсора, а значит курсор должен быть закрыт. А когда следующая итерация пробует получить данные с закрытого курсора возникает ошибка.
НО! Я пробовал посмотреть атрибут %ISOPEN, предварительно переделав все на явный курсор и НИЧЕГО. То есть атрибут после Rollback все-равно True.
Но на будущее будем знать =)
Смысл курсора такой: идет выгрузка документов в центральную базу с обновлением признака выгрузки. Вся внутренность цикла завернута в exception:
exception
when others then
v_st := SQLERRM;
rollback;
dbms_output.put_line(v_st);
end;
После первой неудачной итерации вижу как дебагер переходит на for s in (select... и выпадает ошибка ORA-1002 Fetch out of sequence
В итоге пришлось поставить Commit перед циклом и все заработало.
Поискал в интернете и нашел статью
Провел свои эксперименты. Первоначально создал две таблички tbl_1 и tbl_2 с одним числовым полем id1 и id2 соответственно. В Test Windows в PL/SQL Developer попытался выполнить такой код:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
i integer; | |
begin | |
insert into tbl_1 | |
(id1) | |
values | |
(1); | |
for s in (SELECT t.* FROM all_objects t where rownum < 3) loop | |
begin | |
insert into tbl_2 | |
(id2) | |
values | |
(1); | |
i := 7 / (2-2); | |
exception | |
when others then | |
rollback; | |
dbms_output.put_line(SQLERRM); | |
end; | |
end loop; | |
end; |
И после первой итерации получаем "ORA-01002 Fetch out of sequence", а в DBMS Output только одну запись: ORA-01476: divisor is equal to zero.
Меняем код - добавляем Commit перед циклом и все отрабатывает без ошибок. На выходе 2 записи:
ORA-01476: divisor is equal to zero
ORA-01476: divisor is equal to zero
Пробуем использовать Savepoint:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*using savepoint*/ | |
declare | |
i integer; | |
cnt number := 0; | |
begin | |
insert into tbl_1 | |
(id1) | |
values | |
(1); | |
for s in (SELECT t.* FROM all_objects t where rownum < 3) loop | |
cnt := cnt + 1; | |
execute immediate 'savepoint svp'||cnt; | |
begin | |
insert into tbl_2 | |
(id2) | |
values | |
(1); | |
i := 7 / (2-2); | |
exception | |
when others then | |
execute immediate 'rollback to savepoint svp'||cnt; | |
dbms_output.put_line(SQLERRM || ' => ' || cnt); | |
end; | |
end loop; | |
end; |
На выходе получаем 2 записи:
ORA-01476: divisor is equal to zero => 1
ORA-01476: divisor is equal to zero => 2
Вольный перевод причины возникновения ошибки: Rollback возвращает нас к состоянию до открытия курсора, а значит курсор должен быть закрыт. А когда следующая итерация пробует получить данные с закрытого курсора возникает ошибка.
НО! Я пробовал посмотреть атрибут %ISOPEN, предварительно переделав все на явный курсор и НИЧЕГО. То есть атрибут после Rollback все-равно True.
Но на будущее будем знать =)
Немає коментарів:
Дописати коментар