sql >> Base de Datos >  >> RDS >> Oracle

¿Oracle revierte la transacción en caso de error?

¡Esta es una pregunta interesante!

Cuando Oracle encuentra un error, revertirá la declaración actual. , no la transacción. Una sentencia es cualquier instrucción de nivel superior, puede ser una sentencia SQL (INSERTAR, ACTUALIZAR...) o un bloque PL/SQL.

Esto significa que cuando una declaración (por ejemplo, un procedimiento pl/sql llamado desde java) devuelve un error, Oracle pondrá la transacción en el mismo estado lógico que tenía antes de la llamada. Esto es inmensamente útil, no tiene que preocuparse por procedimientos a medio ejecutar (**).

Este hilo en AskTom cubre el mismo tema:

[la declaración] O bien sucede ENTERAMENTE o NO sucede ENTERAMENTE y la forma en que funciona es que la base de datos hace el equivalente lógico de:

begin
   savepoint foo;
   <<your statement>>
exception
   when others then rollback to foo; 
                    RAISE;
end;

Esta característica, en mi opinión, es la razón por la que es mucho más fácil escribir código de base de datos (*) en pl/sql que en cualquier otro idioma.

(*) código que interactúa con Oracle DB, por supuesto, supongo que los lenguajes de procedimiento nativos de los otros DBMS tienen características similares.

(**) Esto solo se refiere a DML ya que DDL no es transaccional en Oracle. Tenga cuidado también con algunos paquetes DBMS que actualizan el diccionario de datos (como DBMS_STATS ), a menudo hacen cambios similares a DDL y emiten confirmaciones. Consulte la documentación en caso de dudas.

Actualización: este comportamiento es uno de los conceptos más importantes en PL/SQL, proporcionaré un pequeño ejemplo para demostrar la atomicidad de las declaraciones 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

Oracle revirtió la transacción hasta el punto justo antes de llamar a p1. No hay trabajo a medias hecho. Es como si nunca se hubiera llamado al procedimiento p1.