Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle annule-t-il la transaction en cas d'erreur ?

c'est une question intéressante !

Lorsqu'Oracle rencontre une erreur, il annule l'instruction actuelle , pas la transaction. Une instruction est une instruction de niveau supérieur, il peut s'agir d'une instruction SQL (INSERT, UPDATE...) ou d'un bloc PL/SQL.

Cela signifie que lorsqu'une instruction (par exemple une procédure pl/sql appelée depuis java) renvoie une erreur, Oracle mettra la transaction dans le même état logique qu'avant l'appel. C'est extrêmement utile, vous n'avez pas à vous soucier des procédures à moitié exécutées (**).

Ce fil sur AskTom couvre le même sujet :

[l'instruction] se produit ENTIÈREMENT ou NE se produit PAS ENTIÈREMENT et la façon dont cela fonctionne est que la base de données fait l'équivalent logique de :

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

Cette fonctionnalité, à mon avis, est la raison pour laquelle il est beaucoup plus facile d'écrire du code de base de données (*) en pl/sql que dans n'importe quel autre langage.

(*) code qui interagit avec une base de données Oracle bien sûr, je suppose que les langages procéduraux natifs des autres SGBD ont des fonctionnalités similaires.

(**) Cela ne concerne que les DML puisque les DDL ne sont pas transactionnels dans Oracle. Soyez également prudent avec certains packages SGBD qui mettent à jour le dictionnaire de données (comme DBMS_STATS ), ils effectuent souvent des modifications de type DDL et émettent des commits. Reportez-vous à la documentation en cas de doute.

Mise à jour : ce comportement est l'un des concepts les plus importants en PL/SQL, je vais donner un petit exemple pour démontrer l'atomicité des instructions 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 a annulé la transaction au point juste avant d'appeler p1. Il n'y a pas de travail à moitié fait. C'est comme si la procédure p1 n'avait jamais été appelée.