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
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 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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With