BEGIN - END block atomic transactions in PL/SQL

Firstly, BEGIN..END are merely syntactic elements, and have nothing to do with transactions.

Secondly, in Oracle all individual DML statements are atomic (i.e. they either succeed in full, or rollback any intermediate changes on the first failure) (unless you use the EXCEPTIONS INTO option, which I won't go into here).

If you wish a group of statements to be treated as a single atomic transaction, you'd do something like this:

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;

That way, any exception will cause the statements in this block to be rolled back, but any statements that were run prior to this block will not be rolled back.

Note that I don't include a COMMIT - usually I prefer the calling process to issue the commit.


It is true that a BEGIN..END block with no exception handler will automatically handle this for you:

BEGIN
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
END;

If an exception is raised, all the inserts and updates will be rolled back; but as soon as you want to add an exception handler, it won't rollback. So I prefer the explicit method using savepoints.


BEGIN-END blocks are the building blocks of PL/SQL, and each PL/SQL unit is contained within at least one such block. Nesting BEGIN-END blocks within PL/SQL blocks is usually done to trap certain exceptions and handle that special exception and then raise unrelated exceptions. Nevertheless, in PL/SQL you (the client) must always issue a commit or rollback for the transaction.

If you wish to have atomic transactions within a PL/SQL containing transaction, you need to declare a PRAGMA AUTONOMOUS_TRANSACTION in the declaration block. This will ensure that any DML within that block can be committed or rolledback independently of the containing transaction.

However, you cannot declare this pragma for nested blocks. You can only declare this for:

  • Top-level (not nested) anonymous PL/SQL blocks
  • List item
  • Local, standalone, and packaged functions and procedures
  • Methods of a SQL object type
  • Database triggers

Reference: Oracle

Tags:

Oracle

Plsql