PL/SQL value_error exception not getting caught - oracle

This is my Department table:
create table Department(
DeptNo int primary key,
DeptName varchar2(21) not null,
DeptLocation varchar2(13) not null
);
I am trying to insert value for DeptName column with length more than accepted i.e. 21, which means I should get "VALUE_ERROR" exception.
The plsql code I am running is:
begin
insert into department values(1, 'Some random department name', 'SomeLocation');
exception
when value_error then
dbms_output.put_line('Cannot store the value!');
end;
As I am trying to catch the exception, it is not getting caught. I am getting the error:
ORA-12899: value too large for column "SQL_ZIRHWMLFPCEAKPGYGJJZLSIFI"."DEPARTMENT"."DEPTNAME" (actual: 27, maximum: 21) ORA-06512: at line 2
ORA-06512: at "SYS.DBMS_SQL", line 1721
But if I change my exception from "value_error" to "others"
begin
insert into department values(1, 'Some random department name', 'SomeLocation');
exception
when others then
dbms_output.put_line('Cannot store the value!');
end;
then I get the expected output
Cannot store the value!
Where could I have gone wrong? Please let me know. Thanks!
PS: I am running all the code on livesql.oracle.com

Ideally, what you are using is correct and it should had worked as desired. But the exception VALUE_ERROR behaves differently in somecases. See the below illustrative example.
As per the documentation value_error comes when there is an
arithmetic, conversion, truncation, or size-constraint error occurs.
For example, when your program selects a column value into a character
variable, if the value is longer than the declared length of the
variable, PL/SQL aborts the assignment and raises VALUE_ERROR. In
procedural statements, VALUE_ERROR is raised if the conversion of a
character string into a number fails.
The last line says, In procedural statements, VALUE_ERROR is raised if the conversion of a character string into a number fails., but when i run this in a block it rasied INVALID_NUMBER exception.
SQL> declare
2 n number;
3 begin
4 select to_number('a')
5 into n
6 from dual
7 ;
8 exception
9 when value_error
10 then
11 dbms_output.put_line ('Value Error');
12 when invalid_number
13 then
14 dbms_output.put_line ('Invalid Number');
15 end;
16 /
Invalid Number
PL/SQL procedure successfully completed.
I expected that it would raise the VALUE_ERROR but it didn't. So it might be the case that Oracle was not able to raise value_error in your case and when you used WHEN OTHERS it was caught.
Edit:
Ok. So is it possible somehow to catch value_error exception by giving
the value longer than the declared length of the variable?
Explicit Raise of System Exception : Not very elegant but you can do it as below.
declare
var int;
var1 varchar2(21);
var2 varchar2(13);
begin
var1:='Some random department name';
var2:= 'SomeLocation'
If var1 > 21 then
RAISE VALUE_ERROR;
END IF;
If var2 > 13 then
RAISE VALUE_ERROR;
END IF;
insert into department values(1, var1, var2);
exception
when value_error then
dbms_output.put_line('Cannot store the value!');
end;

VALUE_ERROR was not the exception raised when you ran your code, if you want, you can defined an EXCEPTION and catch it, see below code for sample,
DECLARE
ORA_12899 EXCEPTION;
PRAGMA EXCEPTION_INIT(ORA_12899, -12899);
begin
insert into department values(1, 'Some random department name', 'SomeLocation');
exception
when ORA_12899 then
dbms_output.put_line('Cannot store the value!');
end;
/
Below code will have a VALUE_ERROR;
DECLARE
ORA_12899 EXCEPTION;
PRAGMA EXCEPTION_INIT(ORA_12899, -12899);
v_dept VARCHAR2(20);
begin
v_dept := 'Some random department name';
insert into department values(1, v_dept, 'SomeLocation');
exception
when ORA_12899 then
dbms_output.put_line('Cannot store the value!');
end;
/

Related

Exception error when creating procedure oracle sql developer

i have been whacking my brain for the past 2 hours can't find a solution to this error. I am creating a simple procedure to find an employee. PL/SQL keeps giving me error. What is the problem ? what am i doing wrong here ?
This is my Procedure:
create or replace PROCEDURE find_employee (employeeNo IN number) as
INVALID_ID exception;
TOO_MANY_ROWS exception;
res number;
BEGIN
dbms_output.enable;
Select count(*) into res from employee where ID=employeeNo;
if (res>1)then -- Checking that the total count of the employee is 1 or not
raise TOO_MANY_ROWS; -- if greater then 1 then it raise TOO_MANY_ROWS error
ELSE IF (NOT EXISTS (Select ID from employee where ID=employeeNo)) -- Checking that the employeeNo user passes exist or not
then
raise INVALID_ID; -- if employeeNo doesnot exit then display invalid id message
ELSE
Select* from Employee where ID=employeeNo; -- else return employee info whose id==employeeNo
END IF;
EXCEPTION
when TOO_MANY_ROWS then
DBMS_OUTPUT.PUT_LINE ('Too many Rows with same employee id');
when INVALID_ID then
DBMS_OUTPUT.PUT_LINE ('Invalid employee id');
END find_employee;
And error is this:
Error(15,1): PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following: ( begin case declare end exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
Error(20,18): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: end not pragma final instantiable order overriding static member constructor map
Please God Help me :'(
You're missing END IF (line #16). it is easier to spot it if you write formatted code (nested IF should have been indented).
SQL> create or replace PROCEDURE find_employee (employeeNo IN number) as
2 INVALID_ID exception;
3 TOO_MANY_ROWS exception;
4 res number;
5 BEGIN
6 dbms_output.enable;
7 Select count(*) into res from employee where ID=employeeNo;
8 if (res>1)then -- Checking that the total count of the employee is 1 or not
9 raise TOO_MANY_ROWS; -- if greater then 1 then it raise TOO_MANY_ROWS error
10 ELSE IF (NOT EXISTS (Select ID from employee where ID=employeeNo)) -- Checking that the employeeNo user passes exist or not
11 then
12 raise INVALID_ID; -- if employeeNo doesnot exit then display invalid id message
13 ELSE
14 Select* from Employee where ID=employeeNo; -- else return employee info whose id==employeeNo
15 END IF;
16 END IF; --> this is missing
17 EXCEPTION
18 when TOO_MANY_ROWS then
19 DBMS_OUTPUT.PUT_LINE ('Too many Rows with same employee id');
20 when INVALID_ID then
21 DBMS_OUTPUT.PUT_LINE ('Invalid employee id');
22 END find_employee;
As #Dornaut commented, that code probably isn't the best one could produce. Here's another option; see if it helps.
CREATE OR REPLACE PROCEDURE find_employee (employeeNo IN NUMBER)
AS
res NUMBER;
e_row employee%ROWTYPE;
BEGIN
SELECT *
INTO e_row
FROM employee
WHERE id = employeeNo;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('Invalid employee ID');
WHEN TOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line ('Too many rows with same employee ID');
END find_employee;
So: if SELECT returns NO_DATA_FOUND or TOO_MANY_ROWS, it'll be handled. Otherwise, it'll fetch the whole row into a variable.

How to put 2 condition after AS in a procedure

I want to put 2 condition after the keyword AS in a procedure which are INVALID_BUDGET EXCEPTION and Event_ID varchar2(8) but this will cause error in oracle.
CREATE OR REPLACE PROCEDURE PRC_ADD_OVER_BUDGET_EVENT(V_EventType IN VARCHAR,V_EventBudget IN NUMBER,V_organizerID IN VARCHAR,v_FoodBeverage IN NUMBER,v_wine IN NUMBER ,v_Decoration IN NUMBER,v_rentalfee IN NUMBER,v_facility IN NUMBER)
AS INVALID_BUDGET EXCEPTION AND Event_ID varchar2(8);
PRAGMA exception_init(INVALID_BUDGET,-20000);
BEGIN
INSERT INTO Event values ( next_eventid_seq,v_eventType,v_eventbudget,null,null,null,v_organizerID) RETURNING EVENTid INTO event_ID;
INSERT INTO EventCost values (next_Costid_seq,v_FoodBeverage,v_Wine,v_Decoration,v_RentalFee,v_Facility,event_ID);
EXCEPTION WHEN INVALID_BUDGET THEN DBMS_OUTPUT.PUT_LINE(u'\000A' || 'Please enter budget of above 50000.');
End;
/
How to put the two condition in a procedure without any error.
Extra question: Can procedure handle two exception handler?
For multiple exception handling in oracle you can use this syntax. The exception-handling block contains series of WHEN condition to handle the exception.
BEGIN
<execution block>
.
.
EXCEPTION
WHEN <exceptionl_name>
THEN
<Exception handling code for the “exception 1 _name’' >
WHEN OTHERS
THEN
<Default exception handling code for all exceptions >
END;
Please refer the link
Variable definitions are separated by a semi-colon:
CREATE OR REPLACE PROCEDURE PRC_ADD_OVER_BUDGET_EVENT
(V_EventType IN VARCHAR,
V_EventBudget IN NUMBER,
V_organizerID IN VARCHAR,
v_FoodBeverage IN NUMBER,
v_wine IN NUMBER,
v_Decoration IN NUMBER,
v_rentalfee IN NUMBER,
v_facility IN NUMBER)
AS
INVALID_BUDGET EXCEPTION;
Event_ID varchar2(8);
PRAGMA exception_init(INVALID_BUDGET,-20000);
BEGIN
INSERT INTO Event
values (next_eventid_seq, v_eventType, v_eventbudget,
null, null, null, v_organizerID)
RETURNING EVENTid INTO event_ID;
INSERT INTO EventCost
values (next_Costid_seq, v_FoodBeverage, v_Wine, v_Decoration,
v_RentalFee, v_Facility, event_ID);
EXCEPTION
WHEN INVALID_BUDGET THEN
DBMS_OUTPUT.PUT_LINE(u'\000A' || 'Please enter budget of above 50000.');
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE(u'\000A' || 'Attempt to insert duplicate value ' ||
SQLERRM);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(u'\000A' || 'Something bad happened! ' || SQLERRM);
End;
And you can add as many exception handlers to your exception block as you want.
Best of luck.

PL/SQL VALUE_ERROR exception not raised where expected

I am sure my question has a simple theoretical answer but I cannot find it.
I have a procedure which accepts as parameter a NUMBER. It also have the VALUE_ERROR and OTHERS exceptions:
create or replace procedure test( p1 number) is
begin
null;
exception
when VALUE_ERROR then
RAISE_APPLICATION_ERROR(-20001, 'value_error');
when others then
RAISE_APPLICATION_ERROR(-20000, 'others');
end;
I am executing the procedure with a VARCHAR2 paramter:
execute test('a');
... an I expect that the error message displayed to be
ORA-20001 value_error
but, unfortunately, I got:
Error report - ORA-06502: PL/SQL: numeric or value error: character to
number conversion error ORA-06512: at line 1
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
Can anyone explain this, or share a link where it is explained why I do not receive expected error message?
Thank you very much,
As Nicholas mentioned you don't get your message because the exception is thrown not inside the procedure but before executing it.
Let's look at an example:
create or replace procedure test( p1 number) is
begin
null;
exception
when VALUE_ERROR then
RAISE_APPLICATION_ERROR(-20001, 'PROC value_error');
when others then
RAISE_APPLICATION_ERROR(-20000, 'PROC others');
end;
/
begin
test('a');
exception
when VALUE_ERROR then
RAISE_APPLICATION_ERROR(-20001, 'OUT value_error');
when others then
RAISE_APPLICATION_ERROR(-20000, 'OUT others');
end;
What happens here is that you're calling a procedure that requires number as parameter so Oracle tries conversion during execution of anonymous block. You can't see the message from the procedure because before entering the procedure the conversion exception is thrown.
Now let's see what happens if we change the procedure:
create or replace procedure test( p1 varchar2) is
param number;
begin
param := p1;
exception
when VALUE_ERROR then
RAISE_APPLICATION_ERROR(-20001, 'PROC value_error');
when others then
RAISE_APPLICATION_ERROR(-20000, 'PROC others');
end;
/
begin
test('a');
exception
when VALUE_ERROR then
RAISE_APPLICATION_ERROR(-20001, 'OUT value_error');
when others then
RAISE_APPLICATION_ERROR(-20000, 'OUT others');
end;
Or just:
begin
test('a');
end;
to see the error thrown in the procedure.
Now the procedure requires number within its body; when execution reaches that point it throws the conversion error, from within the procedure itself.

DBMS Pl/SQL -- What would be output ... please explain?

SQL> DESC hostel;
Name Null? Type
------------------------------------ -------- -------------------
HOSTELID NOT NULL VARCHAR2(4)
ROOMSAVAILABLE NUMBER(3)
HOSTELTYPE VARCHAR2(1)
HOSTELFEE NUMBER(6)
SQL> SELECT * FROM hostel;
HOST ROOMSAVAILABLE H HOSTELFEE
------- ---------------------- ---- ---------------------
H1 2 M 2000
H2 3 F 3000
Above is shown a table hostel and values in it.
What would be the output of following pl/sql program?
please explain in detail.
CREATE OR REPLACE PROCEDURE sp_validatehostelid
(p_hostelid IN hostel.hostelid%TYPE,
p_hostelfee OUT hostel.hostelfee%TYPE
)
IS
v_count NUMBER;
v_hostelfee hostel.hostelfee%TYPE;
BEGIN
SELECT COUNT(*) INTO v_count FROM hostel WHERE hostelid=p_hostelid;
IF v_count=0 THEN
RAISE_APPLICATION_ERROR(-20000,'Invalid Hostel id');
ELSE
SELECT hostelfee INTO v_hostelfee FROM hostel WHERE hostelid=p_hostelid;
DBMS_OUTPUT.PUT_LINE('Hostel Fee:'||v_hostelfee);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Other Errors in Procedure');
END sp_validatehostelid;
Procedure created.
DECLARE
g_hostelfee hostel.hostelfee%TYPE;
BEGIN
sp_validatehostelid('H5',g_hostelfee);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Other Errors in Block');
END;
"What will be the output? given that there is no row having hostelid =
'H5'"
Assuming you run this in a client with serveroutput enabled the output will be
Other Errors in Procedure
PL/SQL procedure successfully completed.
SQL>
Why?
The first select statement is a count, which cannot hurl a NO_DATA_FOUND exception.
The next line raises a user-defined exception, -20000.
This passes control to the exception handler block. -20000 is not NO_DATA_FOUND so the WHEN OTHERS clause is executed, which displays the message above.
The exception handler does not raise an exception itself, which is very bad practice. So the flow returns to the calling block.
Because no exception was found the calling block thinks the called procedure executed successfully, and so processing terminate cleanly. That's why it is bad practice not re-raise exceptions.
Note that if you run this without enabling serveroutput first the output will be:
PL/SQL procedure successfully completed.
SQL>
CREATE OR REPLACE PROCEDURE sp_validatehostelid
(
p_hostelid IN hostel.hostelid%TYPE,
p_hostelfee OUT hostel.hostelfee%TYPE
)
IS
v_count NUMBER;
v_hostelfee hostel.hostelfee%TYPE;
BEGIN
/* Count rows in 'hostel' table for given ID */
SELECT COUNT(*) INTO v_count FROM hostel WHERE hostelid=p_hostelid;
/* If there is noting in the table */
IF v_count=0 THEN
/* raise exception */
RAISE_APPLICATION_ERROR(-20000,'Invalid Hostel id');
ELSE
/* select fee from the 'hostel' table */
SELECT hostelfee INTO v_hostelfee FROM hostel WHERE hostelid=p_hostelid;
/* print the fee */
DBMS_OUTPUT.PUT_LINE('Hostel Fee:'||v_hostelfee);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Other Errors in Procedure');
END sp_validatehostelid;
DECLARE
g_hostelfee hostel.hostelfee%TYPE;
BEGIN
sp_validatehostelid('H5',g_hostelfee);
/*
**Here something should be done with 'g_hostelfee' variable
*/
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Other Errors in Block');
END;
If there is a row with hostelid = 'H5' collect the fee for given ID, print it and pass it out.
NOTE: It will work only for one row per ID. If there is more than one. TO_MANY_VALUES exception will be raised.

Handle ORACLE Exceptions

I need to handle the ORA-01400 error (cannot insert NULL into ("SCHEMA"."TABLE_NAME"."COLUMN_NAME") ) using a exception handle.
ORACLE Predefine a few Exceptions like (ACCESS_INTO_NULL, ZERO_DIVIDE and so on), but apparently does not define an Exception for the ORA-01400 error, how do I handle this particular error code?
I need something like this (other suggestions are accepted).
....
...
INSERT INTO MY_TABLE (CODE, NAME) VALUES (aCode,aName);
COMMIT;
EXCEPTION
WHEN NULL_VALUES THEN /* i don't know this value , exist?*/
Do_MyStuff();
WHEN OTHERS THEN
raise_application_error(SQLCODE,MY_OWN_FORMAT_EXCEPTION(SQLCODE,SQLERRM),TRUE);
END;
The pre-defined PL/SQL exceptions are special to Oracle. You really can't mess with those. When you want to have a set of predefined exceptions of your own you can't declare them "globally" like the standard ones. Instead, create an exceptions package which has all of the exception declarations and use that in your application code.
Example:
CREATE OR REPLACE PACKAGE my_exceptions
AS
insert_null_into_notnull EXCEPTION;
PRAGMA EXCEPTION_INIT(insert_null_into_notnull, -1400);
update_null_to_notnull EXCEPTION;
PRAGMA EXCEPTION_INIT(update_null_to_notnull, -1407);
END my_exceptions;
/
Now use the exception defined in the package
CREATE OR REPLACE PROCEDURE use_an_exception AS
BEGIN
-- application specific code ...
NULL;
EXCEPTION
WHEN my_exceptions.insert_null_into_notnull THEN
-- application specific handling for ORA-01400: cannot insert NULL into (%s)
RAISE;
END;
/
Source: http://www.orafaq.com/wiki/Exception
you can define your own exceptions, like variables (they will have the same scope as other variables so you can define package exception, etc...):
SQL> DECLARE
2 NULL_VALUES EXCEPTION;
3 PRAGMA EXCEPTION_INIT(NULL_VALUES, -1400);
4 BEGIN
5 INSERT INTO t VALUES (NULL);
6 EXCEPTION
7 WHEN null_values THEN
8 dbms_output.put_line('null value not authorized');
9 END;
10 /
null value not authorized
PL/SQL procedure successfully completed
You can handle exception by its code like this:
....
...
INSERT INTO MY_TABLE (CODE, NAME) VALUES (aCode,aName);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -1400 THEN
Do_MyStuff();
ELSE
raise_application_error(SQLCODE,MY_OWN_FORMAT_EXCEPTION(SQLCODE,SQLERRM),TRUE);
END IF;
END;
INSERT INTO MY_TABLE (CODE, NAME) VALUES (aCode,aName);
COMMIT;
EXCEPTION
WHEN NULL_VALUES /* i don't know this value , exist?*/
emesg := SQLERRM;
dbms_output.put_line(emesg);
WHEN OTHERS THEN
emesg := SQLERRM;
dbms_output.put_line(emesg);
END;
SQLERRM shows the sql error message
http://www.psoug.org/reference/exception_handling.html

Resources