essa é uma pergunta interessante!
Quando o Oracle encontra um erro, ele reverte a instrução atual , não a transação. Uma instrução é qualquer instrução de nível superior, pode ser uma instrução SQL (INSERT, UPDATE...) ou um bloco PL/SQL.
Isso significa que quando uma instrução (por exemplo, um procedimento pl/sql chamado de java) retornar um erro, o Oracle colocará a transação no mesmo estado lógico de antes da chamada. Isso é imensamente útil, você não precisa se preocupar com procedimentos meio executados (**).
Este tópico no AskTom aborda o mesmo tópico:
[a instrução] ou TOTALMENTE acontece ou TOTALMENTE NÃO acontece e a maneira como funciona é que o banco de dados faz o equivalente lógico de:
begin
savepoint foo;
<<your statement>>
exception
when others then rollback to foo;
RAISE;
end;
Esse recurso, na minha opinião, é o motivo pelo qual é muito mais fácil escrever código de banco de dados (*) em pl/sql do que em qualquer outra linguagem.
(*) código que interage com um banco de dados Oracle claro, suponho que as linguagens procedurais nativas dos outros SGBDs tenham características semelhantes.
(**) Isso diz respeito apenas ao DML, pois o DDL não é transacional no Oracle. Tenha também cuidado com alguns pacotes DBMS que atualizam o dicionário de dados (como
DBMS_STATS
), eles geralmente fazem alterações semelhantes a DDL e emitem commits. Consulte a documentação em caso de dúvidas. Atualização: esse comportamento é um dos conceitos mais importantes em PL/SQL, vou fornecer um pequeno exemplo para demonstrar a atomicidade das instruções pl/sql :
SQL> CREATE TABLE T (a NUMBER);
Table created
SQL> CREATE OR REPLACE PROCEDURE p1 AS
2 BEGIN
3 -- this statement is successful
4 INSERT INTO t VALUES (2);
5 -- this statement will raise an error
6 raise_application_error(-20001, 'foo');
7 END p1;
8 /
Procedure created
SQL> INSERT INTO t VALUES (1);
1 row inserted
SQL> EXEC p1;
begin p1; end;
ORA-20001: foo
ORA-06512: at "VNZ.P1", line 5
ORA-06512: at line 2
SQL> SELECT * FROM t;
A
----------
1
O Oracle reverteu a transação para o ponto imediatamente antes de chamar p1. Não há meio trabalho feito. É como se o procedimento p1 nunca tivesse sido chamado.