Tout d'abord, BEGIN..END
ne sont que des éléments syntaxiques et n'ont rien à voir avec les transactions.
Deuxièmement, dans Oracle, toutes les instructions DML individuelles sont atomiques (c'est-à-dire qu'elles réussissent intégralement ou annulent toute modification intermédiaire lors du premier échec) (sauf si vous utilisez l'option EXCEPTIONS INTO, que je n'aborderai pas ici).
Si vous souhaitez qu'un groupe d'instructions soit traité comme une seule transaction atomique, procédez comme suit :
BEGIN
SAVEPOINT start_tran;
INSERT INTO .... ; -- first DML
UPDATE .... ; -- second DML
BEGIN ... END; -- some other work
UPDATE .... ; -- final DML
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO start_tran;
RAISE;
END;
De cette façon, toute exception entraînera l'annulation des instructions de ce bloc, mais toutes les instructions exécutées avant ce bloc ne sera pas annulé.
Notez que je n'inclus pas de COMMIT - généralement, je préfère que le processus d'appel émette le commit.
Il est vrai qu'un bloc BEGIN..END sans gestionnaire d'exception s'en chargera automatiquement pour vous :
BEGIN
INSERT INTO .... ; -- first DML
UPDATE .... ; -- second DML
BEGIN ... END; -- some other work
UPDATE .... ; -- final DML
END;
Si une exception est déclenchée, toutes les insertions et mises à jour seront annulées ; mais dès que vous souhaitez ajouter un gestionnaire d'exceptions, il ne sera pas annulé. Je préfère donc la méthode explicite utilisant des points de sauvegarde.