Oracle
 sql >> Database >  >> RDS >> Oracle

Oracle esegue il rollback della transazione in caso di errore?

questa è una domanda interessante!

Quando Oracle rileva un errore, eseguirà il rollback dell'istruzione corrente , non la transazione. Un'istruzione è qualsiasi istruzione di primo livello, può essere un'istruzione SQL (INSERT, UPDATE...) o un blocco PL/SQL.

Ciò significa che quando un'istruzione (ad esempio una procedura pl/sql chiamata da java) restituisce un errore, Oracle metterà la transazione nello stesso stato logico di prima della chiamata. Questo è immensamente utile, non devi preoccuparti di procedure eseguite a metà (**).

Questa discussione su AskTom tratta lo stesso argomento:

[l'affermazione] o accade INTERAMENTE o NON accade INTERAMENTE e il modo in cui funziona è che il database fa l'equivalente logico di:

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

Questa caratteristica, secondo me, è il motivo per cui è molto più semplice scrivere il codice del database (*) in pl/sql che in qualsiasi altra lingua.

(*) codice che interagisce con un DB Oracle ovviamente, suppongo che i linguaggi procedurali nativi degli altri DBMS abbiano caratteristiche simili.

(**) Ciò riguarda solo DML poiché i DDL non sono transazionali in Oracle. Fai attenzione anche con alcuni pacchetti DBMS che aggiornano il dizionario dei dati (come DBMS_STATS ), spesso eseguono modifiche simili a DDL ed emettono commit. Fare riferimento alla documentazione in caso di dubbi.

Aggiornamento: questo comportamento è uno dei concetti più importanti in PL/SQL, fornirò un piccolo esempio per dimostrare l'atomicità delle istruzioni 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 ha riportato la transazione al punto appena prima di chiamare p1. Non c'è lavoro a metà. È come se la procedura p1 non fosse mai stata chiamata.