"Кроме того, если хранимая подпрограмма дает сбой с необработанным исключением, PL / SQL не откатывает работу базы данных, выполненную подпрограммой."
Приведенная выше цитата конкретно относится к хранимым подпрограммам, но следующий фрагмент кода является анонимным блоком, а не хранимой подпрограммой
BEGIN
-- call the upper procedure
p1;
END;
Цитата как таковая не применяется. Отказ анонимного блока верхнего уровня - это тот, который выполняет откат (как и любой другой оператор SQL)
Тестирование с использованием следующего кода показывает, что к тому времени, когда срабатывает триггер SERVERERROR (т. Е. ДО возврата к хосту), значения INSERT значений 1 и 10 уже откатаны (поскольку повторная вставка 1 не приводит к сбою). на дубликат ключа или тупик).
drop table test_se_auto_tbl;
create table test_se_auto_tbl (id number(2) primary key, val varchar2(20));
create or replace trigger test_se_auto_trg after servererror on schema
begin
for c_rec in (select id, val from test_se_auto_tbl) loop
dbms_output.put_line(c_rec.id||':'||c_rec.val);
end loop;
dbms_output.put_line('Trigger');
insert into test_se_auto_tbl values (1,'test ');
end;
/
begin
insert into test_se_auto_tbl values (1,'test ');
insert into test_se_auto_tbl values (10,'test 10');
insert into test_se_auto_tbl values (100,'test 100');
end;
/
select id, val from test_se_auto_tbl;
Еще один сценарий, подтверждающий эту гипотезу. В этом случае анонимный блок PL / SQL вызывается в EXECUTE IMMEDIATE, вложенном в другой блок PL / SQL. Несмотря на то, что исключение перехвачено внешним блоком, вставка уже откатана, поскольку EXECUTE IMMEDIATE выполняет атомарный оператор.
DECLARE
v_num NUMBER;
begin
begin
execute immediate
'declare
v_num number(2);
begin
insert into dummy values (1);
dbms_output.put_line(101);
v_num := 100;
end;';
exception
when others then null;
end;
select count(*) into v_num from dummy;
dbms_output.put_line(v_num);
end;
/