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.