Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PL SQL Raise Exception when data found

I've been looking at the predefined Oracle pl/SQL Exceptions. I'm wanting to raise an exception when data is found. I've been able to see the NO_DATA_FOUND exception. But not it's opposite. What would be the best way to do this, or is it not advised to perform this kind of operation.

My Procedure is like the following

PROCEDURE CHECK_ASSIGNED AS

PLACEHOLDER INT;   

BEGIN

SELECT v.id
INTO PLACEHOLDER
FROM vinegar v
WHERE NOT EXISTS (
SELECT 1
FROM home h
WHERE h.sid = v.sid
)

END;
-- when data is found it means that and sid does not exist in the home table
-- should raise exception and stop package
like image 954
Jonnny Avatar asked Jan 15 '15 19:01

Jonnny


People also ask

How do you raise exceptions in PL SQL?

CREATE OR REPLACE PROCEDURE use_salary (salary_in IN NUMBER) IS BEGIN IF salary_in < 0 THEN RAISE VALUE_ERROR; END IF; END; Procedure created. Which in this case simply "mimics" the pre-defined VALUE_ERROR exception and doesn't really add value.

When you need to raise an exception explicitly what does the PL SQL raise exception statement provide?

When an exception is raised, if PL/SQL cannot find a handler for it in the current block, the exception propagates to successive enclosing blocks, until a handler is found or there are no more blocks to search. If no handler is found, PL/SQL returns an unhandled exception error to the host environment.

When Value_error exception is raised?

In procedural statements, VALUE_ERROR is raised if the conversion of a character string into a number fails. (In SQL statements, INVALID_NUMBER is raised.) A program attempts to divide a number by zero.

What are the 3 types of exceptions in Plsql?

There are three types of exceptions: Predefined exceptions are error conditions that are defined by PL/SQL. Non-predefined exceptions include any standard TimesTen errors. User-defined exceptions are exceptions specific to your application.


1 Answers

There is no built in error for "data found", because finding data is not considered an error by Oracle. However, it's not too difficult to treat this case as an error in specific cases.

It depends somewhat on what you want to do with the exception. If you want to react to it in some way within the procedure, you can define your own exception, then raise it:

PROCEDURE check_assigned AS
   exception err_data_found;
   placeholder INT;
BEGIN
   SELECT v.id
   INTO   placeholder
   FROM   vinegar v
   WHERE  NOT EXISTS
             (SELECT 1
              FROM   home h
              WHERE  h.sid = v.sid);

   IF SQL%FOUND THEN
      RAISE err_data_found;
   END IF;
EXCEPTION
   WHEN err_data_found THEN
      NULL;
      --do something
END;

On the other hand, if you just want to return the error to the caller, you can use raise_application_error:

PROCEDURE check_assigned AS
   placeholder INT;
BEGIN
   SELECT v.id
   INTO   placeholder
   FROM   vinegar v
   WHERE  NOT EXISTS
             (SELECT 1
              FROM   home h
              WHERE  h.sid = v.sid);

   IF SQL%FOUND THEN
      raise_application_error (-20001,
                               'Data was found in the vinegar table.');
   END IF;
END;

If the goal is to raise an error if any row exists and continue otherwise, doing it this way is somewhat perilous, as you risk triggering either NO_DATA_FOUND or TOO_MANY_ROWS. You can get around this by selecting a count as suggested in the comments, but I prefer to use an explicit cursor to avoid those issues.

PROCEDURE check_assigned AS
   placeholder INT;

   CURSOR cur_vinegar_check IS
      SELECT v.id
      INTO   placeholder
      FROM   vinegar v
      WHERE      NOT EXISTS
                    (SELECT 1
                     FROM   home h
                     WHERE  h.sid = v.sid)
             AND ROWNUM = 1;
BEGIN
   OPEN cur_vinegar_check;
   FETCH cur_vinegar_check INTO placeholder;

   IF SQL%FOUND THEN
      raise_application_error (-20001,
                               'Data was found in the vinegar table.');
   END IF;

   CLOSE cur_vinegar_check;
END check_assigned;

You'll notice that I added AND ROWNUM = 1 to the query. This is one of the few times that rownum is predictable in an outer query: all you care about is if a row exists; you don't care which row it is. If there is a possibility that you'll get a lot of rows returned, this can have significant performance benefits.

like image 53
Allan Avatar answered Mar 02 '23 07:03

Allan