For det første BEGIN..END
er blot syntaktiske elementer og har intet at gøre med transaktioner.
For det andet, i Oracle er alle individuelle DML-udsagn atomare (dvs. de enten lykkes fuldt ud eller ruller eventuelle mellemliggende ændringer tilbage ved den første fejl) (medmindre du bruger EXCEPTIONS INTO-indstillingen, som jeg ikke vil komme ind på her).
Hvis du ønsker, at en gruppe af udsagn skal behandles som en enkelt atomtransaktion, ville du gøre noget som dette:
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;
På den måde vil enhver undtagelse medføre, at sætningerne i denne blok bliver rullet tilbage, men alle sætninger, der blev kørt før denne blok vil ikke blive rullet tilbage.
Bemærk, at jeg ikke inkluderer en COMMIT - normalt foretrækker jeg opkaldsprocessen for at udstede commit.
Det er rigtigt, at en BEGIN..END-blok uden undtagelsesbehandler automatisk vil håndtere dette for dig:
BEGIN
INSERT INTO .... ; -- first DML
UPDATE .... ; -- second DML
BEGIN ... END; -- some other work
UPDATE .... ; -- final DML
END;
Hvis der opstår en undtagelse, vil alle indsættelser og opdateringer blive rullet tilbage; men så snart du vil tilføje en undtagelsesbehandler, vil den ikke rulle tilbage. Så jeg foretrækker den eksplicitte metode, der bruger savepoints.