Eles não parecem:
set timing on
set serveroutput on
declare
x number := 0;
begin
dbms_output.put_line('No inner blocks');
for i in 1..1000000 loop
x := x + 1;
end loop;
dbms_output.put_line(x);
end;
/
anonymous block completed
Elapsed: 00:00:00.095
No inner blocks
1000000
Funciona ao mesmo tempo, com um pouco de variação em cada sentido, como:
declare
x number := 0;
begin
dbms_output.put_line('Nested inner blocks');
for i in 1..1000000 loop
begin
begin
begin
begin
x := x + 1;
exception
when others then
raise;
end;
exception
when others then
raise;
end;
exception
when others then
raise;
end;
exception
when others then
raise;
end;
end loop;
dbms_output.put_line(x);
end;
/
anonymous block completed
Elapsed: 00:00:00.090
Nested inner blocks
1000000
Claro que é possível que o compilador esteja removendo as camadas redundantes, mas não tenho certeza se realmente pode com os manipuladores de exceção, pois isso afetaria o resultado.
Não vi nenhuma limitação sobre a profundidade dos blocos aninhados - a documentação apenas diz 'os blocos podem ser aninhados'. O modelo que você está usando, capturando um erro específico e permitindo que outros se propaguem, é bom e bastante padrão - embora obviamente em seu exemplo artificial não seja necessário, mas você sabe disso.