Пропуснахте някои други части от книгата. Да, Стивън е вярно – ако възникне изключение в блок, всички предходни DML ефекти остават на място. И все пак в книгата трябва да има друго споменаване, че всяко изпълнение на SQL или PL/SQL оператор от най-високо ниво (т.е. също анонимен блок) отваря курсор за този израз и ако има изключение по време на изпълнението на курсора, всички DML ефекти са изпълнени по време на изпълнението на курсора се връщат назад. Може би един прост пример ще ви даде представа...
Във вашия оригинален пример вие изпълнихте ...
BEGIN
DELETE FROM dml_exception;
raise value_error;
END;
... като изявление от най-високо ниво. Да, в края на блока, макар и все още в него, вашето delete
ефектите останаха на мястото си. И все пак вашият блок повдигна изключение, което се разпространи чак до курсора от най-високо ниво. По този начин, за да се придържаме към принципите на атомарност
, Oracle върна всички чакащи ефекти на отворения курсор.
Ако извикате своя PL/SQL блок от друг PL/SQL блок от най-високо ниво, който обработва и не повдига повторно изключението, повдигнато в PL/SQL блока от по-ниско ниво, ...
BEGIN
BEGIN
DELETE FROM dml_exception;
raise value_error;
END;
EXCEPTION
WHEN others THEN NULL;
END;
..., след това вашето delete
ефектите остават на мястото си. (И тъй като в този блок няма ангажимент, в крайна сметка имате транзакция в ход.)