Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

O Oracle reverte a transação em caso de erro?


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.