Exception handling - plsql - plsql

I have a problem. Am doing an insert function
case f1.RFD_CATEGORY_CODE when'O1' then 'C1GBC'
when 'O2' then 'C2GBC' else null end
the field is mandatory and thus instead of null i need to show an error message if the code is not taking C1GBC or C2GBC. and if the code is taking C1GBC or C2GBC then show successful as message.
i have create an exception below but am getting error
create or replace procedure CTP_CODE as
declare
--RFD_CAT_ERR varchar2;
RFD_CAT_ERR EXCEPTION;
begin
if RFD_CATEGORY_CODE is '01' then RFD_CATEGORY_CODE is 'C1GBC';
DBMS_OUTPUT.PUT_LINE ('No1. Successful Operation');
else
if RFD_CATEGORY_CODE is '02' then RFD_CATEGORY_CODE is 'C2GBC';
DBMS_OUTPUT.PUT_LINE ('No2. Successful Operation');
end if;
raise RFD_CAT_ERR;
end if;
EXCEPTION
when RFD_CAT_ERR then
DBMS_OUTPUT.PUT_LINE ('Error message!');
end;
/

Wrong Code also wrong syntax..
Whenever your code goes in else condition it will throw error as after executing 2nd if it will go to "raise RFD_CAT_ERR;" part and raise an exception.
so u should handle error in elsif after 2nd If condition.

You say the field is mandatory. If by that you mean the field in the table is constrained as not null then you don't have to worry about raising an exception. The insert statement will do that for you. All you have to do is catch it in your exception handler and use RAISE_APPLICATION_ERROR to return a meaningful message.
Do that rather than try to print an error message. If your procedure is called by a batch process, there will be no one there to see it.

This works for me :D
CASE f1.RFD_CATEGORY_CODE
WHEN 'O1' THEN 'C1GBC'
WHEN 'O2' THEN 'C2GBC'
ELSE 'error'
Then raise any errors for exception

Related

How to remove extra information form error message after executing a package body?

I want to remove extra information form error message after executing a package body.
Example:
If I run a anonymous block then the error message come like -
ERROR at line 1:
ORA-20010: Object ID PE556092 is not Produced by the Template TP000036
ORA-06512: at "EXAMPLE.TESTPROC", line 5
ORA-06512: at line 1
But i want to show only the below error message:
ORA-20010: Object ID PE556092 is not Produced by the Template TP000036
You can use the below to get the Error Code and Message respectively:
dbms_output.put_line('Error code: '||sqlcode);
dbms_output.put_line('Error msg: '||sqlerrm);
Read more about SQLERRM.
You can do that by defining an exception and mapping it to the SQLCODE of the raised error. Then you handle the logic in the exception handler.
Example, here I map to error -20010 (the one you are using):
declare
err_obj_not_produced exception;
pragma exception_init (err_obj_not_produced, -20010);
l_object varchar2 (50);
l_template varchar2 (50);
begin
run_your_code ('With values');
exception
when err_obj_not_produced then
return 'Object ID ' || l_object || ' is not Produced by the Template ' || l_template;
end;
Another one way to hide information about previous errors. Suppose you have two procedures:
create or replace procedure proc1 is
begin
raise no_data_found;
end;
/
create or replace procedure proc2 is
begin
proc1;
exception
when no_data_found then
raise_application_error(-20010, 'There is no spoon, Neo.');
end;
/
when you run a block in SQL*Plus, you get:
SQL> begin
proc2;
end;
/
begin
*
ERROR at line 1:
ORA-20010: There is no spoon, Neo.
ORA-06512: at "DEV.PROC2", line 6
ORA-06512: at line 2
You can change proc2 like this:
create or replace procedure proc2 is
begin
proc1;
end;
/
And call it like this with desired result:
SQL> begin
begin
proc2;
exception
when no_data_found then
raise_application_error(-20010, 'There is no spoon, Neo.', false);
end;
exception
when others then
dbms_output.put_line(SQLERRM);
end;
/
ORA-20010: There is no spoon, Neo.
PL/SQL procedure successfully completed.
This example shows how third parameter of raise_application_error procedure works. If you pass false, procedure deletes information about previously raised exceptions from error stack. It also will be impossible to get this information using dbms_utility.format_error_backtrace.
As Jon Heller noticed in comments, hiding information about exceptions is a bad practice (and using when others then without raise too, as Jeffry Kemp noticed), so, I hope you know what you are doing. This way or another, it is a shooting yourself in the foot.

Highest record in PL/SQL

I have created a query that displays highest returned items from a table. My query it works perfectly with no errors! However, I want an efficient way of converting the query to PL/SQL block. The purpose of conversion is to handle errors.
SELECT ITEM_NO, MAX(QUANTITY) AS MAXIMUM
FROM ITEMS
WHERE CAT_NO >= (
SELECT MAX(ITEM_NUM) FROM ORDER
WHERE STATUS IN('ONE ITEM RETURNED','ALL ITEMS RETURNED')
)
GROUP BY ITEM_NO
ORDER BY ITEM_NO ASC;
Here's a way we do some exception handling in packages. I altered it to use your code as an example. Maybe you can use some ideas from it.
At the top, set a CONSTANT to the name of the procedure, and some variables to catch Oracle SQL error number and message in. Then in the body of the procedure, there is an anonymous block containing the select. First we set a variable to indicate where we are (err_loc) in case there are multiple locations where an error could be caught in one block. Then the select is issued. If an error occurs, it's caught by the EXCEPTION clause. Error info from Oracle is caught in the err* variables, the err_string is built and then emailed via the UTL_MAIL package. RAISE raises the error so the program halts. It's set up like this to be generic as possible, we can drop in the template, change the MBR_NAME, SQL, err_loc and that's it.
PROCEDURE TEST_PROC AS
MBR_NAME CONSTANT VARCHAR2(100) := 'TEST_PROC'; -- For use in error handling. Package member name.
err_nbr NUMBER; -- Holds a SQL error number if an exception occurs.
err_msg VARCHAR2(1000); -- Holds a SQL error message if an exception occurs.
err_string VARCHAR2(2000);
BEGIN
BEGIN
err_loc := 'Selecting max quantity'; -- Email subject
SELECT ITEM_NO, MAX(QUANTITY) AS MAXIMUM
FROM ITEMS
WHERE CAT_NO >= (SELECT MAX(ITEM_NUM)
FROM ORDER
WHERE STATUS IN('ONE ITEM RETURNED','ALL ITEMS RETURNED')
)
GROUP BY ITEM_NO
ORDER BY ITEM_NO ASC;
EXCEPTION
WHEN OTHERS THEN
err_nbr := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 1000);
err_string := 'ERROR: ' || err_nbr || ' occurred: ' || err_msg;
-- PKG_NAME and err_email_recip set in the body.
UTL_MAIL.send(sender => PKG_NAME||'.'||MBR_NAME||'#yourcompany.com',
recipients => err_email_recip,
subject => 'ERROR '|| err_loc,
message => CHR(13))||err_string);
RAISE;
END;
END TEST_PROC;
Have a look at cursors and records.
That way you have fetch data from the query and process the line if needed.
I don't have a database by hand to test my code, but this might give you an idea how a cursor and record work.
In order to capture a EXCEPTION you could add an exception handler and let it log the record you where busy with when the exception occured.
DECLARE
CURSOR CursorName IS
SELECT ColumnOne
FROM TableA
WHERE Name = 'Me';
RecordNumber CursorName%ROWTYPE;
BEGIN
-- Fetch the records from the cursor.
OPEN CursorName;
LOOP
FETCH CursorName INTO RecordNumber;
-- Do something with the record.
EXIT WHEN CursorName %NOTFOUND;
END LOOP;
CLOSE CursorName;
END;
/
Adding a error handeling would be done right above END:
EXCEPTION
WHEN OTHERS THEN
-- Log error message.
END;
/
Link: Error handeling
Does that answer you question a bit?

return keyword wont work... how to stop running of program?

I had two buttons that do different job but there is check data entry in common
so I made a program unit for that check then I call it from these two buttons
but my problem is that when there is an error within the check I got the message for user and all things I made but the its get back to the code within button and continue progressing I set a return keywords at end of each condition to sop the code from running but its not working please whats the problem ? how I can stop my code until the error check passed ?!!
example of check data entry program unit
PROCEDURE CHECK_ENTRY IS
BEGIN
IF :block1.text_item1 IS NULL THEN
SET_ITEM_INSTANCE_PROPERTY('block1.text_item1',CURRENT_RECORD,VISUAL_ATTRIBUTE,'ERROR_ATR');
SHOW_MESSAGE('example msg .');
RETURN;
ELSIF :block2.text_item2 IS NULL THEN
SET_ITEM_INSTANCE_PROPERTY('block2.text_item2',CURRENT_RECORD,VISUAL_ATTRIBUTE,'ERROR_ATR');
SHOW_MESSAGE('example msg2 .');
RETURN;
END IF ;
END;
example of code within on_button_press trigger
PROCEDURE procedure_name IS
BEGIN
IF FORM_SUCCESS THEN
DISPLAY_ERROR;
:block1.text_item1:= :block2.text_item2;
:block2.text_item2:=:block1.text_item1;
**CHECK_ENTRY;** /* here is the calling of previous program unit that check the data entry then get back to here in case there is no error and continue commit the data and disabling text item so user wont be able to modify the data */
COMMIT_FORM;
program_unit('ORDER_DONE');
ELSE
ROLLBACK;
DISPLAY_ERROR;
SHOW_MESSAGE('please connect administrator.');
END IF;
END;
Your code should be like this:
PROCEDURE CHECK_ENTRY IS
BEGIN
IF :block1.text_item1 IS NULL THEN
SET_ITEM_INSTANCE_PROPERTY('block1.text_item1',CURRENT_RECORD,VISUAL_ATTRIBUTE,'ERROR_ATR');
SHOW_MESSAGE('example msg .');
raise form_trigger_failure;
ELSIF :block2.text_item2 IS NULL THEN
SET_ITEM_INSTANCE_PROPERTY('block2.text_item2',CURRENT_RECORD,VISUAL_ATTRIBUTE,'ERROR_ATR');
SHOW_MESSAGE('example msg2 .');
raise form_trigger_failure;
END IF ;
END;
PROCEDURE procedure_name IS
BEGIN
:block1.text_item1:= :block2.text_item2;
:block2.text_item2:=:block1.text_item1;
CHECK_ENTRY;
IF FORM_SUCCESS THEN
DISPLAY_ERROR;
COMMIT_FORM;
program_unit('ORDER_DONE');
ELSE
ROLLBACK;
DISPLAY_ERROR;
SHOW_MESSAGE('please connect administrator.');
END IF;
END;

Display custom message when constraint is violated PL/SQL

I'm writing a pl/sql procedure. I've got a constraint on a column which doesn't allow values below 0 and above 500. I need to display a custom message if this constraint is violated (eg. "ID out of range"). Currently this is the exception and also the output in getting. There is another procedure that is outputting the error, hence the use raise_applcation_error.
Exception
when VALUE_ERROR then
raise_application_error(-20002, 'Customer ID out of range');
Error Message
"ORA-20000: ORA-02290: check constraint (s5849497.CK_ID_RANGE) violated"
What I would like
"ORA-20000: Customer ID out or range"
Here is the whole block if it helps
set serveroutput on;
---------------------------------------------------------------
alter table customer
add constraint ck_id_range
check (custid > 0 and custid < 500);
---------------------------------------------------------------
create or replace procedure ADD_CUSTOMER_TO_DB(pcustid number, pcustname varchar2) as
begin
insert into customer
values (pcustid,pcustname,0,'OK');
exception
when DUP_VAL_ON_INDEX then
raise_application_error(-20001, 'Duplicate customer ID');
when VALUE_ERROR then
raise_application_error(-20002, 'Customer ID out of range');
when others then
raise_application_error(-20000, SQLERRM);
end;
Thank you
I'm guessing that you're getting an ORA-02290 error. The way to catch this in an exception handler is to declare and initialize an exception for the particular error code (in this case, -2290) and then use your custom exception in the handler:
create or replace procedure ADD_CUSTOMER_TO_DB(pcustid number,
pcustname varchar2)
as
eCheck_constraint_violated EXCEPTION;
PRAGMA EXCEPTION_INIT(eCheck_constraint_violated, -2290);
begin
insert into customer
values (pcustid,pcustname,0,'OK');
exception
when DUP_VAL_ON_INDEX then
raise_application_error(-20001, 'Duplicate customer ID');
when eCheck_constraint_violated then
raise_application_error(-20002, 'Customer ID out of range');
when others then
raise_application_error(-20000, SQLERRM);
end;
As you'll see above, I just replaced VALUE_ERROR with the newly-defined exception.
If by chance the error you're getting is not -2290, just put the error you're seeing in PRAGMA EXCEPTION_INIT invocation above instead of -2290.
Share and enjoy.

Catching a constraint violation in psql

I am using sql developer, and have added a constraint to one of my tables.
constraint valid_gender check(gender in ('M','F','I','T'))
When I try to add an entry with say 'x' for gender using a plsql procedure, it fails with constraint violation (as it should).
I want to add a "Catch" to the plsql procedure so that if valid_gender is voilated I can raise_application_error specific to it. Is this possible?
Oracle will raise an exception that says:
ORA-02290: check constraint (yourschema.valid_gender) violated
You can catch that in an exception handler and raise your own exception instead using raise_application_error in a couple of ways.
1) You can specifically trap the ORA-02290 exception like this:
declare
e_check_violated exception
pragma exception_init (e_check_violated, -2290);
begin
insert ...
exception
when e_check_violated then
if sqlerrm like '%(yourschema.valid_gender)%' then
raise_application_error(-20001,'Invalid gender');
else
raise;
end if;
end;
2) You can trap all exceptions and inspect them:
begin
insert ...
exception
when others then
if sqlerrm like 'ORA-02290:%(yourschema.valid_gender)%' then
raise_application_error(-20001,'Invalid gender');
else
raise;
end if;
end;
In a large application it is quite common to have an exception handling procedure to generalise this and look up the constraint-specific message in a table.
use anonym block in your code...
BEGIN
INSERT or update...
EXCEPTION
WHEN dup_val_on_index THEN
RISE...
END;
You could just test it first:
if gender_value not in ('M','F','I','T') then
raise_application_error...
end if;

Resources