Skip to Main Content
  • Questions
  • Exceptions handling - how to rollback correctly

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, gaia.

Asked: February 20, 2017 - 11:27 am UTC

Last updated: January 07, 2019 - 7:02 am UTC

Version: 11 / 12

Viewed 50K+ times! This question is

You Asked

Hi everyone,

my question is about how to correctly handling exception in a pl/sql procedure: I need to rollback everything made in a begin-end block if there's any kind of exception.

Here's the example code:

create table prova (cod number);
alter table
add constraint pk_prova primary key (cod)
;


create or replace procedure prova_1
is
l_err_num number;
l_err_desc varchar2(100);

begin
insert into prova values(1);
insert into prova values(1);
insert into prova values(2);
commit;

EXCEPTION
    WHEN OTHERS THEN
        l_err_num := SQLCODE;
        l_err_desc := SQLERRM;
        DBMS_OUTPUT.PUT_LINE(l_err_num ||': '||l_err_desc);
        RAISE;
commit;

end; 


As i compile and execute the procedure, i can see that with the "RAISE" command in the exception block, i find no row in the prova table. Instead, taking off the "raise" command, i find a 1 in the table...
Is this the correct way to use the "RAISE" command? Or there's a better way to handle the rollback?

For better undestanding: in the real procecdure there's no dbms_output but an insert in a log table.

Many thanks,
Gaia

and Chris said...

The behaviour you see relates to implicit rollbacks. Oracle Database rolls back statements that raise exceptions. The database sees the PL/SQL call as a single statement. So when you re-raise the error, sending it back to the client, it undoes everything in the call. Tom explains this in more detail at:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0%3A%3A%3A%3AP11_QUESTION_ID:43818437682131

So you don't need to explicitly code the rollback in your exception block. Though explicitly doing this won't hurt.

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

A reader, February 21, 2017 - 4:04 pm UTC

Thanks Chris,

I used the "raise" exactly because i read that other answer but i wasn't sure to have it understood correctly.

So the command is usefull to both rollback if anything goes wrong AND send the error message to the application that executes the procedure.

Many thanks.
Connor McDonald
February 22, 2017 - 1:22 am UTC

Just a clarification on "Though explicitly doing this won't hurt."

There is *difference* between

exception
  when others then
     -- some stuff
     rollback;
     raise;
end;


and

exception
  when others then
     -- some stuff
     raise;
end;


Because a failed procedure call will rollback work *that the procedure* has done. A an explicit "rollback" call will rollback work that the procedure has done *and* any uncommitted work done before the procedure started.

Rollback after Exception else Commit

Sam, January 07, 2019 - 5:15 am UTC

--SET TRANSACTION READ WRITE;
BEGIN
SAVEPOINT ABC;
update table_A set is_active ='Y' where id = 10;
update table_A set createdon ='Y' where id = 20; --exception
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO ABC;
COMMIT;
END;


--createdon is of datetime type and has an exception. So rollback will happen.

Connor McDonald
January 07, 2019 - 7:02 am UTC

True, but now you

- have got a whole stack of extra code
- need to make assumptions about what constitutes a "transaction"

xzc

xc, July 07, 2020 - 8:37 am UTC


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library