ORACLE PL/SQL : How to pass an exception into a procedure - oracle

Is there a way to pass exception into a procedure to call "raise" after doing some actions to process exception. So that the outer code block will get the exact exception that was raised
Something like this:
begin
...
exception
when others then
error_handler( err );
end;
procedure error_handler ( err ) is
begin
/*
here some code to handle and log the exception...
*/
raise err;
end;
Or the only way is to pass SQLCODE and SQLERRM into the procedure and later call raise_application_error( SQLCODE, SQLERRM )?

If I understood you correctly, this is what you're asking.
Sample log table:
SQL> create table err_log
2 (program varchar2(30),
3 datum date,
4 sqlcode number
5 );
Table created.
Logging procedure should be an autonomous transaction so that you could commit in it, without affecting main transaction.
SQL> create or replace procedure error_handler
2 (p_program in varchar2, p_sqlcode in number)
3 is
4 pragma autonomous_transaction;
5 begin
6 insert into err_log (program, datum, sqlcode)
7 values (p_program, sysdate, p_sqlcode);
8 commit;
9 end;
10 /
Procedure created.
Another procedure (whose execution you're logging); it'll raise division by zero. See lines #8 and #9 which call the logging procedure and then just re-raise the error:
SQL> create or replace procedure p_test is
2 l_program varchar2(30) := 'P_TEST';
3 l_value number;
4 begin
5 l_value := 1 / 0;
6 exception
7 when others then
8 error_handler(l_program, sqlcode);
9 raise;
10 end p_test;
11 /
Procedure created.
OK, everything is set. Let's try it:
SQL> exec p_test;
BEGIN p_test; END;
*
ERROR at line 1:
ORA-01476: divisor is equal to zero --> this is result of RAISE in line #9
ORA-06512: at "SCOTT.P_TEST", line 9
ORA-06512: at "SCOTT.P_TEST", line 5
ORA-06512: at line 1
Log table contents:
SQL> select * from err_log;
PROGRAM DATUM SQLCODE
------------------------------ ------------------- ----------
P_TEST 01.11.2022 11:13:31 -1476
SQL>
You asked, literally:
How to pass an exception into a procedure?
You can't, as far as I can tell:
SQL> create or replace procedure error_handler_text
2 (p_err in exception) --> if this is what you asked
3 is
4 begin
5 null;
6 end;
7 /
Warning: Procedure created with compilation errors.
SQL> show err
Errors for PROCEDURE ERROR_HANDLER_TEXT:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/13 PLS-00103: Encountered the symbol "EXCEPTION" when expecting one
of the following:
out <an identifier> <a double-quoted delimited-identifier>
table columns long double ref char standard time timestamp
interval date binary national character nchar
The symbol "<an identifier> was inserted before "EXCEPTION" to
continue.
SQL>

Related

plsql pass failure back to executing job

I have a scheduled job in oracle that runs plsql code. I will like to be able to mark the scheduled job as failed if scheduled occur within the code, but I have failed with my googling skills.
So
if a = b then
return (and get the code to fail)
end if;
I assume I am missing something very obvious but cannot find it anywhere.
Thanks
Perhaps this will help demonstrate:
SQL> set serverout on
SQL> --
SQL> create or replace procedure my_proc(p_value number)
2 as
3 ex_custom1 exception;
4 pragma exception_init(ex_custom1,-20001);
5 ex_custom2 exception;
6 pragma exception_init(ex_custom2,-20002);
7 begin
8 if p_value = 1
9 then raise_application_error (-20001,'This is custom error 1');
10 end if;
11 --
12 if p_value = 2
13 then raise_application_error (-20002,'This is custom error 2');
14 end if;
15 --
16 dbms_output.put_line('Non-error completion');
17 exception
18 when ex_custom1
19 then
20 dbms_output.put_line( sqlerrm );
21
22 when ex_custom2
23 then
24 dbms_output.put_line( sqlerrm );
25 end;
26 /
Procedure created.
SQL> show errors
No errors.
SQL> --
SQL> exec my_proc(1);
ORA-20001: This is custom error 1
PL/SQL procedure successfully completed.
SQL> exec my_proc(2);
ORA-20002: This is custom error 2
PL/SQL procedure successfully completed.
SQL> exec my_proc(3);
Non-error completion
PL/SQL procedure successfully completed.
SQL>
SQL>
SQL>
SQL> --
SQL> drop procedure my_proc;
Procedure dropped.
SQL> --
SQL> spo off
~

Need Assistance with PL/SQL Syntax

Can someone please pinpoint the syntax error in the below code.
DECLARE
plsql_blk VARCHAR2 (250);
begin
plsql_blk := 'begin DBMS_STATS.DELETE_TABLE_STATS ('||''''|| OWNER ||''''||','||''''|| TABLE_NAME ||''''||');'
from dba_tables
where owner = 'SYSADM'
and table_name like 'AS_TAO%'
or table_name like 'AS_BP_XLBP_TAO%'
order by table_name; end;';
execute immediate plsql_blk;
end;
/
Thanks in advance.
That would be "too many errors" error (only if it existed).
you can't execute a procedure which "looks like" a SELECT statement. Where did FROM clause come from (as well as the rest of that piece of code)?
if you are using OR among other conditions, you have to enclose it into parenthesis, otherwise you'll get false result
I didn't count them, but it looks as if you got lost in that many single quotes. Instead of that, consider using the q-quoting mechanism which helps A LOT
Let's try to make it work. I don't have your users nor tables so I'll do that in Scott's sample schema.
First, gather statistics (otherwise there's nothing to delete):
SQL> exec dbms_stats.gather_table_stats('SCOTT', 'EMP');
PL/SQL procedure successfully completed.
SQL>
This is a procedure which shows some statistics (why a procedure? So that I wouldn't have to copy/paste the whole code once again at the end of this demonstration):
SQL> create or replace procedure p_getstat(par_table in varchar2)
2 is
3 l_numrows number;
4 l_numblks number;
5 l_avgrlen number;
6 l_cachedblk number;
7 l_cachehit number;
8 begin
9 dbms_stats.get_table_stats
10 (ownname => 'SCOTT',
11 tabname => dbms_assert.simple_sql_name(par_table),
12 numrows => l_numrows,
13 numblks => l_numblks,
14 avgrlen => l_avgrlen,
15 cachedblk => l_cachedblk,
16 cachehit => l_cachehit
17 );
18 dbms_output.put_line(par_table || ' has ' || l_numrows || ' row(s)');
19 end;
20 /
Procedure created.
Let's try it:
SQL> set serveroutput on
SQL>
SQL> exec p_getstat('EMP');
EMP has 14 row(s)
PL/SQL procedure successfully completed.
SQL>
Now, your procedure, fixed. You overcomplicated it by putting everything into dynamic SQL. Loop through tables you're interested in, but execute only the necessary part in dynamic fashion:
SQL> create or replace procedure p_delstat (par_owner in varchar2)
2 is
3 l_str varchar2(200);
4 begin
5 for cur_r in (select owner, table_name
6 from all_tables
7 where owner = dbms_assert.simple_sql_name(par_owner)
8 and ( table_name like 'EMP%'
9 or table_name like 'AS_BP_XLBP_TAO%'
10 )
11 order by table_name
12 )
13 loop
14 l_str := 'begin dbms_stats.delete_table_stats(:a, :b); end;';
15 execute immediate l_str using cur_r.owner, cur_r.table_name;
16 end loop;
17 end;
18 /
Procedure created.
Does it work?
SQL> exec p_delstat('SCOTT');
PL/SQL procedure successfully completed.
SQL>
Seems so; at least, didn't raise any error. Let's check whether statistics for previously mentioned EMP table still exist:
SQL> exec p_getstat('EMP');
BEGIN p_getstat('EMP'); END;
*
ERROR at line 1:
ORA-20000: Unable to get values for table EMP
ORA-06512: at "SYS.DBMS_STATS", line 7688
ORA-06512: at "SCOTT.P_GETSTAT", line 9
ORA-06512: at line 1
SQL>
Nope, statistics is gone. Looks like we've done it correctly.
Adjust that code so that it works in your database, with your user(s) and your table(s).

Oracle INVALID_NUMBER exception in my function does not work

The Oracle function below assign 'A' to number variable.
But the Exception clause does not catch INVALID_NUMBER system exception.
CREATE OR REPLACE FUNCTION TEST2
(P1 IN VARCHAR2)
RETURN NUMBER AS V_VALUE NUMBER;
BEGIN
SELECT(
--SELECT 1/TO_NUMBER(P1)
SELECT 'A'
FROM DUAL
)
INTO V_VALUE
FROM DUAL;
RETURN V_VALUE;
EXCEPTION
WHEN INVALID_NUMBER THEN -- If I change INVALID_NUMBER to OTHERS, then it works.
RETURN -1;
END;
/
SELECT TEST2('1') FROM DUAL;
When I change INVALID_NUMBER to OTHERS, then it works.
How to modify above code to chatch the INVALID_NUMBER exception?
Because you get VALUE_ERROR when ORA-06502 raised as occurs in your case. So, replace INVALID_NUMBER with VALUE_ERROR.
as an example; if the SELECT statement was :
SELECT 5
INTO V_VALUE
FROM DUAL
WHERE TO_NUMBER('A')=1;
you'd get INVALID_NUMBER(ORA-01722) exception.
Some more info (to what Barbaros already told you).
The INVALID_NUMBER Exception (ORA-01722) occurs in a SQL statement when the conversion of a character string into a number fails because the string does not represent a valid number. (In procedural statements, VALUE_ERROR is raised.) This exception is also raised when the LIMIT-clause expression in a bulk FETCH statement does not evaluate to a positive number.
Compare
SQL> select 'a'/2 from dual;
select 'a'/2 from dual
*
ERROR at line 1:
ORA-01722: invalid number
to
SQL> declare
2 l_num number;
3 begin
4 l_num := 'a' / 2;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 4
to
SQL> declare
2 l_num number;
3 begin
4 select 'a' / 2 into l_num from dual;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-01722: invalid number
ORA-06512: at line 4
Isn't that nice of Oracle? More or less the same thing, but different response.

Oracle : How to drop procedures matched by the name mask

I have created two procedures like :
CREATE OR REPLACE procedure PARTNER_OWNER.test_1
as begin
dbms_output.put_line('Hello World 1 !');
end;
and
CREATE OR REPLACE procedure PARTNER_OWNER.test_2
as begin
dbms_output.put_line('Hello World 2 !');
end;
Now I need to drop the procedures at the same time (something like ):
drop procedure PARTNER_OWNER.test_*;
Is there a way to do that?
I would use a select statement to generate the drop statements and then run them.
select 'DROP PROCEDURE PARTNER_OWNER.'||object_name||';'
from dba_objects
where object_name like 'TEST_%' and
owner = 'PARTNER_OWNER';
Bobby
One option is to use dynamic SQL. Here's an example:
SQL> create or replace procedure test_1
2 as begin
3 dbms_output.put_line('Hello World 1 !');
4 end;
5 /
Procedure created.
SQL> create or replace procedure test_2
2 as begin
3 dbms_output.put_line('Hello World 2 !');
4 end;
5 /
Procedure created.
SQL> exec test_1;
Hello World 1 !
PL/SQL procedure successfully completed.
SQL> exec test_2;
Hello World 2 !
PL/SQL procedure successfully completed.
Now, drop them:
SQL> begin
2 for cur_r in (select object_name from user_objects
3 where object_type = 'PROCEDURE'
4 and object_name like 'TEST%')
5 loop
6 execute immediate 'drop procedure ' || cur_r.object_name;
7 end loop;
8 end;
9 /
PL/SQL procedure successfully completed.
The result:
SQL> exec test_1;
BEGIN test_1; END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'TEST_1' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SQL> exec test_2;
BEGIN test_2; END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'TEST_2' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Alternatively, instead of using an anonymous PL/SQL block, you can rewrite it to a procedure and reuse it later. As it accepts a parameter, you can drop any procedure. Pay attention to LIKE (so that you wouldn't drop a procedure you didn't really want to).
SQL> create or replace procedure p_drop_prc(par_procedure_name in varchar2)
2 is
3 begin
4 for cur_r in (select object_name from user_objects
5 where `enter code here`object_type = 'PROCEDURE'
6 and object_name like upper(par_procedure_name) ||'%')
7 loop
8 execute immediate 'drop procedure ' || cur_r.object_name;
9 end loop;
10 end;
11 /
Procedure created.
SQL> exec p_drop_prc('test');
PL/SQL procedure successfully completed.
SQL> exec test_1;
BEGIN test_1; END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'TEST_1' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SQL>
Also, you could add another parameter - object type - so that you could drop any object, not just a procedure.
Obviously, quite a few options; pick the one you find the most appropriate.

Procedure calling gone bad - Statement Ignored

I have the following procedure to insert users in a table:
CREATE OR REPLACE PROCEDURE ELR_ADD_USER
(I_NAME IN VARCHAR2,
I_MORADA IN VARCHAR2,
I_BIRTHDATE IN DATE,
I_COUNTRY IN VARCHAR2,
O_ID OUT NUMBER,
O_ERROR_MSG OUT VARCHAR2)
IS
ERROR_NULL EXCEPTION;
BEGIN
IF I_NAME IS NULL OR
I_MORADA IS NULL OR
I_BIRTHDATE IS NULL OR
I_COUNTRY IS NULL THEN
RAISE ERROR_NULL;
END IF;
O_ID := ELR_seq_USER_ID.nextval;
IF O_ID IS NULL
RAISE ERROR_NULL;
END IF;
INSERT INTO ELR_USERS
VALUES (O_ID, I_NOME, I_MORADA, I_BIRTHDATE, I_COUNTRY);
EXCEPTION
WHEN ERROR_NULL THEN
O_ERROR_MSG := 'NULL FIELDS';
WHEN OTHERS THEN
O_ERROR_MSG := 'UNEXPECTED ERROR: '|| sqlerrm;
END;
/
I think the procedure and it's syntax are correct. However when I'm trying to call it with:
DECLARE
P_NAME VARCHAR2(50);
P_MORADA VARCHAR2(50);
P_BIRTHDATE DATE;
P_COUNTRY VARCHAR2(20);
P_ID NUMBER(20);
P_ERROR_MSG VARCHAR2(4000);
BEGIN
ELR_ADD_USER('ED WARNER','CENAS Street',SYSDATE,
'China', P_ID, P_ERROR_MSG);
IF P_ERROR_MSG IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('ERROR: '||P_ERROR_MSG);
END IF;
END;
/
I get the following message:
Is there something wrong with the calling or the procedure itself?
ORA-06550 followed by PLS-00905 is clearly a compilation error. The procedure is in INVALID state.
Recompile the procedure, and use SHOW ERRORS to get the complete error details.
SHOW ERROR PROCEDURE RMS_MM.ELR_ADD_USER or simply SHOW ERRORS
For example,
SQL> CREATE OR REPLACE PROCEDURE TestProc
2 AS
3 vnum number;
4 BEGIN
5 vnum := vAnotherNum;
6 END;
7 /
Warning: Procedure created with compilation errors.
SQL> execute TestProc();
BEGIN TestProc(); END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object EXAMPLE.TESTPROC is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SQL> show error procedure TestProc;
Errors for PROCEDURE TESTPROC:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/1 PL/SQL: Statement ignored
5/9 PLS-00201: identifier 'VANOTHERNUM' must be declared

Resources