how to handle exception in if condition pl/sql - plsql

ineed your help when i wrote if else condition in plsql to check whether it is even or odd number using if conditopn . if i enter character then it will raise an error.how to handle it using exceptions to understand client. help me
declare
num number:=&number;
begin
if num=1 then
dbms_output.put_line('composite');
else if mod(num,2)=0 then
dbms_output.put_line('even');
else if mod(num,2)=1 then
dbms_output.put_line('odd');
else
dbms_output.put_line('enter proper data');
end if;
end if;
end if;
end;
/

Please see the following working example:
declare
-- user input is always a string so treat it as a string
v_input varchar2(32767) := '&number';
num number;
begin
-- convert input to a number. to_number() throws if input string can't be
-- converted to a number. see to_number() documentation for details.
-- the conversion has to happen inside begin-end block because the exception
-- handler of the block won't catch exceptions raised in declare block.
num:=to_number(v_input);
-- do your math
if num=1 then
dbms_output.put_line('composite');
elsif mod(num,2)=0 then
dbms_output.put_line('even');
elsif mod(num,2)=1 then
dbms_output.put_line('odd');
else
dbms_output.put_line('enter proper data');
end if;
exception
-- the exception raised by to_number()
when value_error then
dbms_output.put_line('not a valid number: ' || v_input);
-- all other exceptions are still raised to the caller.
end;
/
Example results:
SQL> #so
Enter value for number: 1
old 2: v_input varchar2(32767) := '&number';
new 2: v_input varchar2(32767) := '1';
composite
PL/SQL procedure successfully completed.
SQL> #so
Enter value for number: 2
old 2: v_input varchar2(32767) := '&number';
new 2: v_input varchar2(32767) := '2';
even
PL/SQL procedure successfully completed.
SQL> #so
Enter value for number: 3
old 2: v_input varchar2(32767) := '&number';
new 2: v_input varchar2(32767) := '3';
odd
PL/SQL procedure successfully completed.
SQL> #so
Enter value for number: foo
old 2: v_input varchar2(32767) := '&number';
new 2: v_input varchar2(32767) := 'foo';
not a valid number: foo
PL/SQL procedure successfully completed.
SQL>

Related

Loop cursor of ALL_MVIEWS generate PL/SQL Error ORA-06502

i wrote a procedure that deals with writing the contents of the QUERY column of ALL_MVIEWS to a file:
DECLARE
v_out_dir_name VARCHAR2(30) := 'DIR_TEST';
v_out_dir_path VARCHAR2(60);
v_count_object_elab NUMBER := 0;
CURSOR c_mviews IS
SELECT
LOWER(MVIEW_NAME) || '.sql' AS FILE_NAME
, QUERY AS SCRIPT
FROM ALL_MVIEWS
;
v_file UTL_FILE.file_type;
BEGIN
FOR r_mview IN c_mviews LOOP
v_file := UTL_FILE.fopen (v_out_dir_name, r_mview.FILE_NAME, 'w');
UTL_FILE.putf (v_file, r_mview.SCRIPT);
UTL_FILE.fclose (v_file);
v_count_object_elab := v_count_object_elab + 1;
END LOOP;
IF v_count_object_elab = 0
THEN
DBMS_OUTPUT.PUT_LINE('NESSUN FILE ELABORATO');
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERRORE = ' || SQLERRM);
IF UTL_FILE.IS_OPEN (v_file) THEN
UTL_FILE.FCLOSE (v_file);
END IF;
RAISE;
END;
/
But the "FOR r_mview IN c_mviews LOOP" statement generates the following error:
Report error -
ORA-06502: PL/SQL: errore di numero o valore
ORA-06512: a line 35
ORA-06512: a line 16
ORA-06512: a line 16
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.
The error is thrown on a materialized view that has QUERY_LEN = 39000.
How can I solve the problem?
Many thanks in advance.
I don't think you are using UTL_FILE correctly. The putf() procedure is for writing and formatting (using printf() style). Try using just put() instead. I did run your script on my database and it executed fine with putf() and put(), but put() is more appropriate.
Also, beware that QUERY is a LONG. If you have a query over 32k I think you will get the error you are seeing. There are some great write-ups online about how awful LONGs are to work with.
I think easiest thing to do is convert the LONG to CLOB with a CREATE TABLE, read that table and then drop it. Here is a routine to do just that. It will create a copy of all_mviews and convert the query to a CLOB and write that in chunks to a file per view.
DECLARE
v_out_dir_name VARCHAR2(30) := 'MVIEW';
v_count_object_elab NUMBER := 0;
v_cursor SYS_REFCURSOR;
v_file utl_file.file_type;
v_start INTEGER;
v_buffer VARCHAR2(1024);
v_file_name VARCHAR2(1024);
v_query CLOB;
table_or_view_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_or_view_does_not_exist,
-00942);
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE all_mviews_clob';
EXCEPTION
WHEN table_or_view_does_not_exist THEN
NULL;
END;
EXECUTE IMMEDIATE 'CREATE TABLE all_mviews_clob AS SELECT mview_name, to_lob(query) AS query FROM all_mviews';
OPEN v_cursor FOR q'[SELECT lower(mview_name) || '.sql' AS file_name,
query AS script
FROM all_mviews_clob]';
LOOP
FETCH v_cursor
INTO v_file_name,
v_query;
EXIT WHEN v_cursor%NOTFOUND;
v_file := utl_file.fopen(location => v_out_dir_name,
filename => v_file_name,
open_mode => 'w');
v_start := 1;
FOR i IN 1 .. ceil(dbms_lob.getlength(lob_loc => v_query) / 1024)
LOOP
v_buffer := dbms_lob.substr(lob_loc => v_query,
amount => 1024,
offset => v_start);
IF v_buffer IS NOT NULL THEN
utl_file.put(file => v_file,
buffer => v_buffer);
utl_file.fflush(file => v_file);
END IF;
v_start := v_start + 1024;
END LOOP;
utl_file.fclose(v_file);
v_count_object_elab := v_count_object_elab + 1;
END LOOP;
IF v_count_object_elab = 0 THEN
dbms_output.put_line('no mviews');
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('eror = ' || SQLERRM);
IF utl_file.is_open(v_file) THEN
utl_file.fclose(v_file);
END IF;
RAISE;
END;
/

Why RAISE_APPLICATION_ERROR() function is not working in this code?

I want to throw a customize error when the query fetches no record. But the below code is not throwing my desired error. It is throwing the system generated an error. Could you please help me? What mistake I am making?
DECLARE
v_em_id NUMBER := &var_id;
v_name varchar2(20);
BEGIN
SELECT first_name INTO v_name FROM employees WHERE employee_id =v_em_id;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20002,'Employee not exist');
END IF;
DBMS_OUTPUT.PUT_LINE('Hi! '|| v_name);
END;
I should throw the error code:-20002
and error message: Employee not exist.
You can try the below code...
DECLARE
v_em_id NUMBER := &var_id;
v_name varchar2(20);
BEGIN
SELECT first_name INTO v_name FROM employees WHERE employee_id = v_em_id;
DBMS_OUTPUT.PUT_LINE('Hi! ' || v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20002, 'Employee not exist');
END IF;
END;
If the select statement returns no rows it will raise no_data_found exception. So system is failing before the IF SQL%NOTFOUND THEN line..
SQL%NOTFOUND is useless here. If nothing is found, NO_DATA_FOUND exception is raised so you have to handle that. Here's an example based on Scott's schema:
SQL> declare
2 v_em_id number := &empno;
3 v_name varchar2(20);
4 begin
5 select ename
6 into v_name
7 from emp
8 where empno = v_em_id;
9
10 dbms_output.put_line('Hi, ' || v_name);
11 exception
12 when no_data_found then
13 raise_application_error(-20002, 'Employee does not exist');
14 end;
15 /
Enter value for empno: 7934
Hi, MILLER
PL/SQL procedure successfully completed.
SQL> /
Enter value for empno: 111
declare
*
ERROR at line 1:
ORA-20002: Employee does not exist
ORA-06512: at line 13
SQL>

Procedure error with '&'

error screenshot I am trying to execute the below program in Toad.
create or replace procedure tst_excp as
var_sal number;
var_empid number;
var_excp exception;
begin
select sal into var_sal from emp
where empno = &var_empid;
if var_sal < 4500 then
raise var_excp;
end if;
exception
when var_excp then
dbms_output.put_line ('The salary is low');
end;
and I am getting an error at the line: where empno = &var_empid;
error message is:
PL/SQL: ORA-00936: missing expression
I am planning to pass the value to the variable while executing it.
the & is part of the sqlplus (and TOAD, SQL Developer and PL/SQL Developer) runtime variables. it will prompt you on execution (in your case while compiling the procedure) for an input to replace in the code.
if you want the get an input for the procedure, so it will be added to the where clause on every run, you need to receive it as an input variable:
create or replace procedure tst_excp (var_empid in number) as -- << changed here
var_sal number;
var_empid number;
var_excp exception;
begin
select sal into var_sal from emp
where empno = var_empid; -- << changed here too
if var_sal < 4500 then
raise var_excp;
end if;
exception
when var_excp then
dbms_output.put_line ('The salary is low');
end;

Does member of function work with collection of records in oracle?

I have a index by table of records. Can I use member of function to check if a particular records exist in by PLSQL table or not.
DECLARE
TYPE emp_name_rec is RECORD(
firstname varchar2(10),
lastname varchar2(10),
hiredate varchar2(10));
TYPE staff IS TABLE OF emp_name_rec;
members staff := staff();
rec emp_name_rec;
rec1 emp_name_rec;
BEGIN
rec.firstname := 'peter';
rec.lastname := 'dunn';
rec.hiredate := 'x';
rec1.firstname := 'mary';
rec1.lastname := 'dunn';
rec1.hiredate := 'y';
members.extend;
members(members.last) := rec;
members.extend;
members(members.last) := rec1;
if rec member of members then
dbms_output.put_line('Yes its there');
else
dbms_output.put_line('no its not');
end if;
END;
This doesn't work for me, and I get no error, except I get disconnected... It looks like it compiles but it crashes my session.
I get disconnected when I try your code in Oracle 11g. => It doesn't work! as is
From http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/collections.htm ,
You can check whether a collection is null. Comparisons such as greater than, less than, and so on are not allowed. This restriction also applies to implicit comparisons. [...]
Solution is: write your code:
[..] you must define your own notion of what it means for collections to be greater than, less than, and so on, and write one or more functions to examine the collections and their elements and return a true or false value.
Thus you can't use MEMBER OF directly, but define your own cmp_rec function (which is quite obvious there, but not for Oracle it seems):
DECLARE
TYPE emp_name_rec is RECORD(
firstname varchar2(10),
lastname varchar2(10),
hiredate varchar2(10));
TYPE staff IS TABLE OF emp_name_rec;
members staff := staff();
rec emp_name_rec;
rec1 emp_name_rec;
rec_is_found boolean :=false;
function cmp_rec ( a emp_name_rec, b emp_name_rec)
return boolean is
begin
return a.firstname=b.firstname and a.firstname=b.firstname and a.hiredate=b.hiredate;
end cmp_rec;
BEGIN
rec.firstname := 'peter';
rec.lastname := 'dunn';
rec.hiredate := 'x';
rec1.firstname := 'mary';
rec1.lastname := 'dunn';
rec1.hiredate := 'y';
members.extend;
members(members.last) := rec;
members.extend;
members(members.last) := rec1;
-- we must loop over the collection ourselves
-- - I choosed to look it all, but we could break the loop when found
for i in 1..members.count loop
dbms_output.put_line(members(i).firstname);
if cmp_rec(members(i), rec) then
rec_is_found:=true;
end if;
end loop;
-- if rec member of members then
-- becomes
if rec_is_found then
dbms_output.put_line('Yes its there');
else
dbms_output.put_line('no its not');
end if;
END;

wrirting rollback after handling exception

I have a scenario in which, i am writing the exception like this
when others then
rollback;
p_status := 'ERROR'; -- MODIFIED
p_status_dtl := sqlcode||' - '||substr(sqlerrm,1,100);
end;
if i write like this
exception
when others then
p_status := 'ERROR'; -- MODIFIED
p_status_dtl := sqlcode||' - '||substr(sqlerrm,1,100);
rollback;
end;
does it make a difference if yes what is the difference.
The examples are identical if the variable assignments don't throw (i.e. both p_status and p_status_dtl are correct data type with enough storage).
If the variable assignment throws then in the second example rollback is not executed.
In the example below only checkpoint 1 will be printed:
declare
v_foo varchar2(2) := 'AB';
v_bar number;
begin
-- raises ORA-01476: divisor is equal to zero
v_bar := 1/0;
exception
when others then
dbms_output.put_line('checkpoint 1');
-- raises ORA-06502: PL/SQL: numeric or value error: character string buffer too small
v_foo := 'TOO LONG';
dbms_output.put_line('checkpoint 2');
end;
/

Resources