Home > front end >  Cannot handle raised exception in PL/SQL
Cannot handle raised exception in PL/SQL

Time:12-30

I trying to handle exception if no rows found. In result I see an following error: PL/SQL: unhandled user-defined exception. A user-defined exception was raised by PL/SQL code, but not handled. What I doing wrong?

DECLARE
  my_exception EXCEPTION;
  result1 VARCHAR2(50);
  result2 NUMBER;
BEGIN
  SELECT brand, year INTO result1, result2 FROM cars WHERE car_id=200;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RAISE my_exception;  WHEN my_exception THEN
    DBMS_OUTPUT.PUT_LINE('Exception has been thrown');
END;

CodePudding user response:

You are successfully trapping the NO_DATA_FOUND exception, but within that exception handler you are then raising a new user-defined exception of your own (RAISE my_exception).

When you raise from an exception handler like this, it falls back to the parent block and looks for an exception handler there... but you have no parent block, and so on until it reaches the outermost block. If it isn't caught, it will finally throw the "unhandled user-defined exception" to the client.

If you want to continue execution and do nothing but emit that dbms_output message, then remove the "RAISE my_exception" line and everything to do with that exception. Just put the dbms_output in the handler for NO_DATA_FOUND.

If however you really do want to use a user defined exception, then nest the entire thing in a wrapping parent block and handle it there:

DECLARE
  my_exception exception;
BEGIN
   DECLARE
     result1 VARCHAR2(50);
     result2 NUMBER;
   BEGIN
      SELECT brand, year INTO result1, result2 FROM cars WHERE car_id=200;
   EXCEPTION
     WHEN NO_DATA_FOUND THEN
       RAISE my_exception;
   END;
EXCEPTION
  WHEN my_exception THEN
    dbms_output.put_line("my_exception raised")
END;

CodePudding user response:

The exception handler in the outer block has already been called when the NO_DATA_FOUND exception was raised. If you raise another exception inside the exception handling block then it will not be caught at the same level; instead you either need to:

  1. Wrap the RAISE statement inside its own PL/SQL anonymous block and catch the exception inside the exception handler of that block:
DECLARE
  my_exception EXCEPTION;
  result1 VARCHAR2(50);
  result2 NUMBER;
BEGIN
  SELECT brand, year INTO result1, result2 FROM cars WHERE car_id=200;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    BEGIN
      RAISE my_exception;
    EXCEPTION
      WHEN my_exception THEN
        DBMS_OUTPUT.PUT_LINE('Exception has been thrown');
    END;
END;
/
  1. Wrap the block raising the exception in an outer block and catch the exception there:
DECLARE
  my_exception EXCEPTION;
BEGIN
  DECLARE
    result1 VARCHAR2(50);
    result2 NUMBER;
  BEGIN
    SELECT brand, year INTO result1, result2 FROM cars WHERE car_id=200;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      RAISE my_exception;
  END;
EXCEPTION
  WHEN my_exception THEN
    DBMS_OUTPUT.PUT_LINE('Exception has been thrown');
END;
/

Both of which output:

Exception has been thrown

fiddle

  • Related