Skip to Main Content
  • Questions
  • Ref Cursor Exception: ORA-1403 : No Data Found

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Antonella.

Asked: March 05, 2001 - 11:19 am UTC

Last updated: November 02, 2006 - 9:09 am UTC

Version: 8.1.7

Viewed 10K+ times! This question is

You Asked

Hi Tom,

the example that I send you it works: it's a SELECT INTO Problem.
I have no Scott Schema anymore, sorry.

CREATE OR REPLACE PROCEDURE Test2 (
status OUT NUMBER,
c_value OUT NUMBER
)
IS

BEGIN
Select firm_oid_fk
Into c_value
From T_Firm
where firm_oid_fk = 1 ;

status := 0;

END Test2;

Best Regards
Antonella

Hi Tom
I'm sorry I didn't explain the Problem exactly: I apologize for the confusion.
You are right, it's not a RefCursor Problem anymore.
I give you a complete example:

PROCEDURE Test (
status OUT NUMBER,
c_values OUT NUMBER
)
IS

BEGIN
Open c_values For
Select *
From T_Firm
where firm_oid_fk = 1 ;

status := 0;
END Test;

And the Java Code that calls it, looks like this:

[...]

DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn =
DriverManager.getConnection ("jdbc:oracle:thin:@wvk- server.gft.ch:1521:devzent",
"wvk_dbdev", "wvk_dbdev");

CallableStatement statement =
conn.prepareCall(conn.nativeSQL("{call Test2(?,?)}"));


statement.registerOutParameter(1, Types.NUMERIC);
statement.registerOutParameter(2, Types.NUMERIC);

statement.executeQuery();

System.out.println();
System.out.println("STATUS : " + statement.getLong(1));
System.out.println("VALUE : " + statement.getLong(2));
System.out.println();

statement.close();
conn.close();


Well the problem is that If no Data is read a get an Exception and it takes upto 4 times the time it normally takes to execute successfully the Stored Procedure.
Why?? How can I debug what happens in the JDBC Driver?? How can I trace to a File what happens in the Stored Procedure when I call it from the Java Jdbc Client??

Best Regards
Antonella


Hi Tom,
here are the Additional Informations:
It's easier to get the error if you declare a stored procedure that has only an OUT Parameter, e.g. a VARCHAR2:
Procedure NoDataTest(pippo OUT VARCHAR2) as
Select name into pippo from emp;
[...]






Hi Tom,

I'm experiencing a major Performance Problem with Stored Procedures that bring back Data in a Ref Cursor: every time that No data is selected , Oracle bringt an Exeption back to my JDBC Client--> "ORA 1403: No Data Found".
The Exception Handling takes a lot of Time: it's too expensive.

How can I avoid that the an invalid Ref Cursor is back to the Client?? Can I initialize ref cursors??

Best Regards
Antonella Balduzzi



and Tom said...

Ok, so this is an issue with regards to catching an exception in a java client that was raised by the database (nothing at all to do with ref cursors...)

Thanks to the Piermarini brothers - Mark and Matt - for their help on this one. They figured it out. We don't have a good reason WHY, just that it is this way (as follows, there is a solution)


So, here are the PLSQL snippets we used:

CREATE OR REPLACE
PROCEDURE Test1 ( status OUT NUMBER, c_value OUT NUMBER)
IS
BEGIN
Select 1
Into c_value
From dual
where 1 = 1 ;

status := 0;

END Test1;
/

Test1 Never throws an exception

CREATE OR REPLACE
PROCEDURE Test2 ( status OUT NUMBER, c_value OUT NUMBER)
IS
BEGIN
Select 1
Into c_value
From dual
where 0 = 1 ;

status := 0;

END Test2;
/

Test2 always throws an exception

CREATE OR REPLACE
PROCEDURE Test3 ( status OUT NUMBER, c_value OUT NUMBER)
IS
BEGIN
Select 1
Into c_value
From dual
where 0 = 1 ;

status := 0;

exception
when NO_DATA_FOUND then
status := 1;
END Test3;
/
test3 always throws but also catches and handles the exception and returns a return code to the caller via status

Then the java we test drove this with was:

import java.sql.*;
import oracle.jdbc.driver.*;
import oracle.sql.*;

class test
{

public static void showTimeStamp( String msg )
{
System.out.println( (new
Timestamp(System.currentTimeMillis())).toString() +
":" + msg );
}

static CallableStatement cstmt_persistent;

public static void set_up( Connection conn, String p ) throws Exception
{
cstmt_persistent =
conn.prepareCall("{ call "+p+"( ?, ? ) }" );
cstmt_persistent.registerOutParameter
( 1, java.sql.Types.NUMERIC );
cstmt_persistent.registerOutParameter
( 2, java.sql.Types.NUMERIC );
}

public static void no_exception(Connection conn ) throws Exception
{
if ( cstmt_persistent == null ) set_up(conn,"test1");
cstmt_persistent.execute();
cstmt_persistent.getLong(1);
cstmt_persistent.getLong(2);
}


public static void with_exception(Connection conn ) throws Exception
{
if ( cstmt_persistent == null ) set_up(conn,"test2");
try
{
cstmt_persistent.execute();
}
catch (SQLException e)
{
//e.printStackTrace();
}
}

public static void with_exception2(Connection conn ) throws Exception
{
if ( cstmt_persistent == null ) set_up(conn,"test2");
try
{
cstmt_persistent.execute();
}
catch (SQLException e)
{
cstmt_persistent.clearParameters();
}
}

public static void no_exception_no_data_either(Connection conn )
throws Exception
{
if ( cstmt_persistent == null ) set_up(conn,"test3");
cstmt_persistent.execute();
cstmt_persistent.getLong(1);
cstmt_persistent.getLong(2);
}

public static void main(String args[])throws Exception
{
DriverManager.registerDriver
(new oracle.jdbc.driver.OracleDriver());

Connection conn=DriverManager.getConnection
("jdbc:oracle:thin:@aria-dev:1521:ora816dev"
,"scott","tiger");

DatabaseMetaData meta=conn.getMetaData();
System.out.println
("JDBC driver version is "+meta.getDriverVersion());

conn.setAutoCommit(false);

// stmt.execute( "alter session set sql_trace=true" );

showTimeStamp( "Going to no_exception" );
for( int i = 0; i < 100; i++ ) no_exception(conn);

cstmt_persistent = null;
showTimeStamp( "Going to with_exception" );
for( int i = 0; i < 100; i++ ) with_exception(conn);

cstmt_persistent = null;
showTimeStamp( "Going to with_exception2" );
for( int i = 0; i < 100; i++ ) with_exception2(conn);



cstmt_persistent = null;
showTimeStamp( "Going to with_exception_no_data_either" );
for( int i = 0; i < 100; i++ ) no_exception_no_data_either(conn);

showTimeStamp( "done" );
}
}


Now, it'll run a procedure that gets no exceptions just to baseline.

Then, it runs with exceptions every time. this is noticably slower.

Then it runs with exceptions every time but used "clearParameters" in the exception handler. That Clears the current parameter values immediately. In general, parameter values remain in force for repeated use of a statement. Setting a parameter value automatically clears its previous value. However, in some cases it is useful to immediately release the resources used by the current parameter values; this can be done by calling the method clearParameters. this runs very fast.

Then, it calls a procedure that gets an exception but handles it and returns a return code instead.

The output for example was:

$ java test
JDBC driver version is 8.1.6.2.0
2001-03-06 16:38:53.362:Going to no_exception
2001-03-06 16:38:53.569:Going to with_exception
2001-03-06 16:38:58.598:Going to with_exception2
2001-03-06 16:38:58.684:Going to with_exception_no_data_either
2001-03-06 16:38:58.818:done


so you see the big time delay:

2001-03-06 16:38:53.569:Going to with_exception
2001-03-06 16:38:58.598:Going to with_exception2

5 seconds to call that. Same routine with clearParameters -- less then 1/10 of a second.

The other option is to catch and handle the exception in PLSQL.



Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Hey!!!.......Keep it up

sundar nambuvel, November 19, 2002 - 7:03 pm UTC

Hey dude...your answer is great... Do you know ...by any chance when a exception is raised in the stored procedure..will it hold the transactions (which are dealt in the procedure)in rollback segments to be alive(status=Active) for say 1 hour or something..?!

Tom Kyte
November 19, 2002 - 10:11 pm UTC

transactions stay alive UNTIL you commit or rollback -- period.

Printing RefCursor in SQL*Plus

Robert, November 20, 2002 - 12:14 pm UTC

Tom, re printing refcursor result in SQLPlus...

LMS1@dns > variable rc RefCursor
LMS1@dns > exec tdi_report2.RefCurProcedure2 (:rc, 'SBLD')

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
LMS1@dns > print :rc

SCRI
----
WO7
WP1

2 rows selected.

Elapsed: 00:00:00.01
LMS1@dns > print :rc
SP2-0625: Error printing variable "rc"

I'd expect to be able to print it again...
Why is it gone ?
Doesn't Sqlplus cache the refcursor ?
Thanks


Tom Kyte
November 21, 2002 - 12:36 pm UTC

A ref cursor is really no different then any other cursor.

What if

LMS1@dns > print :rc

SCRI
----
WO7
...... <snipped> ....
WP1

2,000,000 rows selected.

would you *really* want or even desire sqlplus to cache that?

Once fetched -- the rows are "gone"

exceptions

dxl, November 03, 2004 - 11:20 am UTC

So what would your advise be as to whether to put any exception handling in a procedure that returns a ref cursor to a java app??

I mean if all the ref cursor is doing is a simple select then i guess this can't go wrong except for no data found type errors therefore let java handle the exception handling?

What if the procedure performed something else which could go into error before opening a ref cursor or something else which causes the ref cursor to be left open. Should you then code a "WHEN OTHERS" exception close the cursor and re raise?? eg

EXCEPTION
WHEN OTHERS THEN
close P_Cur;
raise;

END;

The reason i don't like this is that you lose the line number where the procedure fell over.

I am trying to avoid the situation where the procedure falls over and the cursor is left open becuase plsql hasn't closed the cursor.
Can I just leave all this up to the java front end?? ie if the procedure falls over then the java must issue a close cursor command, can the java do this?? Is that how you would do it, not have any exceptions handling in the plsql??

Tom Kyte
November 04, 2004 - 1:24 am UTC

a
select columns INTO variables from table where ....

is the *only thing* that raises no-data_found. it is not possible for a ref cursor to raise that exception.


Let me put it to you this way:

what exceptoins are you EXPECTING in this routine that you can catch AND DEAL WITH. If the answer is "well, there are none that I'm expecting", then they are all unexpected and should be allowed to propagate to a level in the code whereby they are "handled" (eg: the caller -- maybe they log the error, maybe they display the error to the end user, maybe they "exit on error")

Unless you are expecting an exception to be raised -- don't catch it. the only thing that could happen is you accidently forget to re-raise it and that would be "a bug (TM)"


that procedure cannot "fall over" except for reasons so bizzare that hey -- the entire status of the application would be in question.

Ref Cursor Exception: ORA-1403 : No Data Found-

Gopesh Sharma, November 02, 2006 - 9:00 am UTC

It is known that a refcursor will not throw an No Data Found exception . Then how one should handle this situation when the data is not there and you want to raise no data found.If these are those procedures where the ref cursor is opened and control returns to calling program then only the calling procedure can know if data is returned or not .Say client is crystal reports then this lack of data created odd situations on UI.

Tom Kyte
November 02, 2006 - 9:09 am UTC

it is known that explicit cursors do not, only select intos do.

it is not a ref cursor thing, it is a CURSOR THING.

I'm not sure what the issue is, having zero rows is not a "bug" or an "error", a result set returns 0, 1 or more rows - if the UI does the wrong thing with zero rows, the UI has what is known as "a bug"

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library