Exit execution when error occurs PL/SQL - oracle

I would like to know, how can I exit the execution when an error occurs. In Microsoft SQL Server there is a RETURN clause, which does the work. But I would like to know similar functionality in Oracle. I am using Oracle Sql Developer. Here is the script I am using:
First block throws error due to Unique Key Violation, even though it throws error the execution goes to next block and executes the insert statement. I want to end the execution or exit at first block of code itself.
Please help me to write the code.
First anonymous PL/SQL block:
set serveroutput on;
BEGIN
insert into test values(1);
insert into test values(1);
COMMIT;
dbms_output.put_line('PRINT SOMETHING 1');
EXCEPTION
WHEN OTHERS THEN
if sqlcode <> 0
then
dbms_output.put_line(SQLCODE || ' ' || SQLERRM);
RAISE;
end if;
return;
END;
/
Second anonymous PL/SQL block:
set serveroutput on;
BEGIN
insert into test values(6);
COMMIT;
dbms_output.put_line('PRINT SOMETHING');
EXCEPTION
WHEN OTHERS THEN
if sqlcode <> 0
then
dbms_output.put_line(SQLCODE || ' ' || SQLERRM);
RAISE;
end if;
return;
END;
/

If you create a stored procedure, you have more control and can exit whenever you like with a return statement.
So create a stored proc:
create or replace procedure myProc as
begin
dbms_ouput.put_line('i am here');
return;
dbms_ouput.put_line('and not here');
end;
Then in sqlplus or developer:
exec myProc();

You can nest the blocks into a single 'program unit'.
In this way an exception in the first block will stop the whole program unit from executing, rather than just being limited in scope to the first block.
set serveroutput on;
BEGIN
BEGIN
insert into test values(1);
insert into test values(1);
COMMIT;
dbms_output.put_line('PRINT SOMETHING 1');
EXCEPTION
WHEN OTHERS THEN
if sqlcode <> 0
then
dbms_output.put_line(SQLCODE || ' ' || SQLERRM);
RAISE;
end if;
return;
END;
BEGIN
insert into test values(6);
COMMIT;
dbms_output.put_line('PRINT SOMETHING');
EXCEPTION
WHEN OTHERS THEN
if sqlcode <> 0
then
dbms_output.put_line(SQLCODE || ' ' || SQLERRM);
RAISE;
end if;
return;
END;
END;
/

You should be able to use "exit" - see the Oracle documentation here: http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12023.htm
Note that this will end your SqlPlus session, but I don't know of another way of doing it aside from using a single block or stored procedure.
Another useful statement is:
WHENEVER SQLERROR EXIT SQL.SQLCODE
Oracle documentation: http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12052.htm

Thanks for your valuable comments.
JoshL, i tried using EXIT but i am ending up with error. Please correct my code( I am new to PL/SQL). "WHENEVER SQLERROR EXIT" is good to use but my issue is that I use these sql scriptsd in InstallShield, so InstallShield installers does not recognize these statements and throws error.
set serveroutput on;
BEGIN
insert into test values(1);
insert into test values(1);
COMMIT;
dbms_output.put_line('PRINT SOMETHING 1');
EXCEPTION
WHEN OTHERS THEN
if sqlcode <> 0
then
dbms_output.put_line(SQLCODE || ' ' || SQLERRM);
RAISE;
exit;
end if;
END;
/

The EXIT command is only for use within a loop in PL/SQL. The EXIT command leaves the loop at that point. If you use the EXIT command outside a loop in PL/SQL the compiler throws an error.
The EXIT command in SQLPlus exits the SQLPlus session.
This is confusing, because they are two different Oracle products. SQL*Plus can run PL/SQL and the EXIT statement is a valid statement in both products, but with different contexts.

Related

Oracle Pl/SQL Exception Flow

Given a simple SP like;
CREATE OR REPLACE PROCEDURE TEST1
AS
BEGIN
EXECUTE IMMEDIATE 'truncate table missingtable';
dbms_output.put_line('here');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
I never get to the output statement, I thought control returned to the same block, which is the only block.. and yes, missingtable reports a -942 if I try to truncate it.
it's a logic problem, in fact the exception happens but you coded to raise an exception only if the return code is different of 942 which is the the error happening.
if you want to continue to the dbms_output in you first block you need an inner exception
CREATE OR REPLACE PROCEDURE TEST1
AS
BEGIN
BEGIN
EXECUTE IMMEDIATE 'truncate table missingtable';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
ELSE
NULL;
END IF;
END;
dbms_output.put_line('here');
END;
/

How to handle different exceptions in PL/SQL differently?

My stored-procedure is looping executing different statements. I want to handle the following situations:
When the statement returns nothing (no_data_found), I want to quietly skip the rest of the loop (continue).
When the statement causes an error of any type, I want to report it, and then skip the rest of the loop (continue);
When the statement finds rows, I want to report it.
The code looks like:
...
LOOP
stmt := 'select * ......';
BEGIN
EXECUTE IMMEDIATE stmt;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
WHEN OTHERS THEN
dbms_out.put_line(stmt || ': ' || SQLCODE);
CONTINUE;
END;
dbms_out.put_line('Found! Use: ' || stmt);
END LOOP;
The above elicits no errors, but the Found-line is printed for every loop-iteration, including for statements, that yield no results...
Why is the CONTINUE-directive ignored -- am I wrong expecting the directive to be obeyed for any exception -- be it NO_DATA_FOUND or anything else?
In your exception block, the action for your NO_DATA_FOUND handler is NULL - so it executes the NULL statement (i.e. does nothing) and falls out of the BEGIN-END block, hitting the dbms_out.put_line('Found! Use: ' || stmt); statement. The only handler which will execute CONTINUE; is the WHEN OTHERS.
One way to get the behavior you describe is to do a SELECT COUNT(*)... into a numeric variable and then just check to see how many rows are returned:
DECLARE
csr SYS_REFCURSOR;
nCount NUMBER;
BEGIN
LOOP
stmt := 'SELECT COUNT(*) FROM (SELECT * from ... WHERE ...)';
OPEN csr FOR stmt;
FETCH csr INTO nCount;
CLOSE csr;
IF nCount > 0 THEN
dbms_out.put_line('Found! Use: ' || stmt);
ELSE
dbms_out.put_line(stmt || ': ' || SQLCODE);
END IF;
END LOOP;
END;
Of course this is not really valid as there's no way for the value of stmt to change, but I suspect your "real" code handles that.

Procedure to delete non existing rows oracle

I wrote a procedure in PL/SQL to delete rows from a table,However,if that record does not exist,then throws some error like this: DBMS_OUTPUT.PUT_LINE('No such record'); My procedure is:
CREATE OR REPLACE PROCEDURE del_cn2
(c_cntry_id IN COUNTRIES.COUNTRY_ID%TYPE
)
IS
v_error_code NUMBER;
BEGIN
DELETE from countries
WHERE country_id =c_cntry_id;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('No such record');
END IF;
EXCEPTION WHEN OTHERS THEN
v_error_code :=SQLCODE;
IF v_error_code =-2292 THEN
RAISE_APPLICATION_ERROR(-20004,'Organization '||TO_CHAR(c_cntry_id)||' site
details defined for it.');
END IF;
END;
/
However,when I execute this procedure and provide a record that does not exist in my table,it gives message "Procedure completed successfully" I am using this to execute:
Execute procedure del_cn2('JJ');
Can someone please suggest?
If you want an exception to be thrown when a value that does not exist in the table is passed in, you would need to actually throw an exception. You shouldn't use dbms_output for any sort of error output. That is a very simplistic debugging tool-- you shouldn't assume that the caller will ever be able to see that output.
My guess is that you want something like
CREATE OR REPLACE PROCEDURE del_cn2
(c_cntry_id IN COUNTRIES.COUNTRY_ID%TYPE
)
IS
BEGIN
DELETE from countries
WHERE country_id =c_cntry_id;
IF SQL%ROWCOUNT = 0
THEN
raise_application_error( -20001, c_cntry_id || ' no such value.' );
END IF;
END;
try to set serverout to ON
example:
create table tst_delete (col1 int);
create procedure p_test_delete as
BEGIN
DELETE FROM tst_delete
WHERE col1 = 1;
IF (SQL%NOTFOUND)
THEN
dbms_output.put_line('No records found');
END IF;
END;
then call the procedure in SqlPlus
SQL> exec p_test_delete;
PL/SQL procedure successfully completed
same issue that you described - no insformation...
next try with output activated
SQL> set serverout on
SQL> exec p_test_delete;
No records found
PL/SQL procedure successfully completed
SQL>

Convert PLSQL script in Unix?

Is possible convert this PL-SQL code to unix code?
declare
tipE varchar(8) := 'TEST';
begin
insert into TABLENAME VALUES (values);
if tipExec = 'TEST' then
dbms_output.put_line('INSERT is ok; called ROLLBACK in '' TEST');
ROLLBACK;
end if;
exception
when DUP_VAL_ON_INDEX then
if tipE = 'TEST' then
raise_application_error(-9999, 'DUPKEY in'' TEST');
else
raise;
end if;
when others then
raise;
end;
Is it possible? I mean i have a parameter "test" or "prod". I have to make an insert and if this insert has a DUPKEY i have to write it in a log. Otherwise i'll write in the log "INSERT is ok". And the code above it's almost the same concept but in oracle. I need this in unix shell. Thanks.
Create your program above as a named PL/SQL procedure, and then you can easily just invoke it from sqlplus via a Unix shell script like this:
sqlplus -s $USERPASS << sqlend
whenever sqlerror exit 1
set heading off
exec your_function('$example_variable');
sqlend
...where $USERPASS is your login mechanism / user&password. If you dont use any function parameters just delete that bit in the brackets.
Have a look at this Oracle tutorial for an example of how to create a procedure from your PLSQL code snippet:
http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html
As a starter, your procedure should look something like this (un-tested):
CREATE OR REPLACE PROCEDURE your_function
IS
tipE varchar(8) := 'TEST';
begin
insert into TABLENAME VALUES (values);
if tipExec = 'TEST' then
dbms_output.put_line('INSERT is ok; called ROLLBACK in '' TEST');
ROLLBACK;
end if;
exception
when DUP_VAL_ON_INDEX then
if tipE = 'TEST' then
raise_application_error(-9999, 'DUPKEY in'' TEST');
else
raise;
end if;
when others then
raise;
end your_function;

The use of sql%notfound on implicit cursor

I'm completely new to oracle PLSQL. Any help is appreicated.
I could not find similiar question on SO (Maybe it's too basic?)
I'm running the code from TOAD, Oracle 11G
SET SERVEROUTPUT ON
DECLARE
var titres%ROWTYPE;
BEGIN
select reference, sicovam into
var.reference, var.sicovam
from titres
where reference = '1234';
if sql%notfound then
dbms_output.put_line('NOT FOUND');
else
dbms_output.put_line(var.reference || ' ' || var.sicovam);
end if;
END;
If the Where Clause can extract one row of data, then it will run the else part
If the Where Clause cannot extract any row, then it will display the error:
ORA-01403: no data found
ORA-06512: at line 4
Can anyone point me in the right direction? Thanks
I have tried using the basic exception handling code
When others then
null;
end;
Then I am getting another strange result:
If the Where Clause can extract one row of data, then it will NOT run the else part or the if part.
When a query inside a pl/sql block returns no rows the NO_DATA_FOUND exception is raised immediately and execution of the block will halt. So the if sql%notfound then condition will never be evaluated. To catch that exception and respond accordingly, you need EXCEPTION section.
SET SERVEROUTPUT ON
DECLARE
var titres%ROWTYPE;
BEGIN
-- In this case you have to be sure that the query returns only one row
-- otherwise the exception ORA-01422 will be raised
select reference, sicovam into
var.reference, var.sicovam
from titres
where reference = '1234';
dbms_output.put_line(var.reference || ' ' || var.sicovam);
EXCEPTION
WHEN NO_DATA_FOUND
THEN dbms_output.put_line('NOT FOUND');
END;
with select into you need to use exceptions NO_DATA_FOUND and TOO_MANY_ROWS
SET SERVEROUTPUT ON
DECLARE
var titres%ROWTYPE;
BEGIN
select reference, sicovam into
var.reference, var.sicovam
from titres
where reference = '1234';
dbms_output.put_line(var.reference || ' ' || var.sicovam);
exception
when no_data_found
then
dbms_output.put_line('NOT FOUND');
when too_many_rows
then
dbms_output.put_line('2+ ROWS found');
END;

Resources