473,398 Members | 2,165 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

SQL status '02000' too early!

Hi everyone,

I'm facing a really wierd issue here. I can't figure out what in the
world could be going on.

I have this open cursor with some records on it. I loop on the records
until I get a status code of '02000'. The problem is, I get this
status code too early, meaning, I get out of the loop before I process
all the records in the cursor.

How can this be explained?! Is there a work around for that?

To keep it simple, I'll only list relevant code from the stored
procedure.

Start code snippet:

DECLARE NOT_END NUMERIC(1) DEFAULT 1; -- used to check for end of
data
DECLARE AT_END CONDITION FOR '02000'; -- condition for end of data
DECLARE CONTINUE HANDLER FOR AT_END SET NOT_END = 0; -- to get out of
loop

OPEN cursorHoldings;

WHILE (NOT_END <> 0) DO
FETCH cursorHoldings INTO var1, var2, (...and so on)
IF (NOT_END <> 0) THEN
/*
Do things here
*/
END IF;
END WHILE;

CLOSE cursorHoldings;

:End code snippet

By the way, I tried different approaches, like changing the continue
handler declaration to

DECLARE CONTINUE HANDLER FOR NOT FOUND SET NOT_END = 0; -- to get out
of loop

It didn't work.

I thought I'd get the number of rows in the result and loop a certain
number of times, but "GET DIAGNOSTICS varName = ROW_COUNT" returned 0.

I searched for something to tell me the row number so that I can store
the current row number and in the next iteration check if I'm in the
same row number I would exit, but I can't find anything to tell me
which row I'm on now. Besides, I don't need to do that, it should work
the way I'm doing it now. At least, this is how the reference does it.

Any help is appreciated.
Nov 12 '05 #1
12 11261

"Tarek M. Nabil" <Ta*********@itworx.com> wrote in message
news:c8**************************@posting.google.c om...
Hi everyone,

I'm facing a really wierd issue here. I can't figure out what in the
world could be going on.

I have this open cursor with some records on it. I loop on the records
until I get a status code of '02000'. The problem is, I get this
status code too early, meaning, I get out of the loop before I process
all the records in the cursor.

How can this be explained?! Is there a work around for that?

To keep it simple, I'll only list relevant code from the stored
procedure.

Start code snippet:

DECLARE NOT_END NUMERIC(1) DEFAULT 1; -- used to check for end of
data
DECLARE AT_END CONDITION FOR '02000'; -- condition for end of data
DECLARE CONTINUE HANDLER FOR AT_END SET NOT_END = 0; -- to get out of
loop

OPEN cursorHoldings;

WHILE (NOT_END <> 0) DO
FETCH cursorHoldings INTO var1, var2, (...and so on)
IF (NOT_END <> 0) THEN
/*
Do things here
*/
END IF;
END WHILE;

CLOSE cursorHoldings;

:End code snippet

By the way, I tried different approaches, like changing the continue
handler declaration to

DECLARE CONTINUE HANDLER FOR NOT FOUND SET NOT_END = 0; -- to get out
of loop

It didn't work.

I thought I'd get the number of rows in the result and loop a certain
number of times, but "GET DIAGNOSTICS varName = ROW_COUNT" returned 0.

I searched for something to tell me the row number so that I can store
the current row number and in the next iteration check if I'm in the
same row number I would exit, but I can't find anything to tell me
which row I'm on now. Besides, I don't need to do that, it should work
the way I'm doing it now. At least, this is how the reference does it.

Any help is appreciated.


I don't know what your programming problem is.

However, the reason that ROW_COUNT is 0 is that DB2 does not know the entire
number of rows in a select cursor until you fetch them (unless cursor
materialization is necessary to return the first row). In some cases,
depending on the isolation level, the answer set could change between the
first fetch and the last fetch.

DB2 does return to you the number of rows updated or deleted in an SQL
statement.
Nov 12 '05 #2
ROW_COUNT was just something I tried in my efforts to work around the
problem, and now according to this, it's obviously not the solution.

It would also help if DB2 had some variable that can tell me the row
number, like ROWNUM in Oracle. That could also be a work around.

But still, this is not the original problem, the original problem is
why the handler for SQLSTATE '02000' is called while there are still
rows left in the cursor.
"Mark A" <ma@switchboard.net> wrote in message news:<_F*****************@news.uswest.net>...
"Tarek M. Nabil" <Ta*********@itworx.com> wrote in message
news:c8**************************@posting.google.c om...
Hi everyone,

I'm facing a really wierd issue here. I can't figure out what in the
world could be going on.

I have this open cursor with some records on it. I loop on the records
until I get a status code of '02000'. The problem is, I get this
status code too early, meaning, I get out of the loop before I process
all the records in the cursor.

How can this be explained?! Is there a work around for that?

To keep it simple, I'll only list relevant code from the stored
procedure.

Start code snippet:

DECLARE NOT_END NUMERIC(1) DEFAULT 1; -- used to check for end of
data
DECLARE AT_END CONDITION FOR '02000'; -- condition for end of data
DECLARE CONTINUE HANDLER FOR AT_END SET NOT_END = 0; -- to get out of
loop

OPEN cursorHoldings;

WHILE (NOT_END <> 0) DO
FETCH cursorHoldings INTO var1, var2, (...and so on)
IF (NOT_END <> 0) THEN
/*
Do things here
*/
END IF;
END WHILE;

CLOSE cursorHoldings;

:End code snippet

By the way, I tried different approaches, like changing the continue
handler declaration to

DECLARE CONTINUE HANDLER FOR NOT FOUND SET NOT_END = 0; -- to get out
of loop

It didn't work.

I thought I'd get the number of rows in the result and loop a certain
number of times, but "GET DIAGNOSTICS varName = ROW_COUNT" returned 0.

I searched for something to tell me the row number so that I can store
the current row number and in the next iteration check if I'm in the
same row number I would exit, but I can't find anything to tell me
which row I'm on now. Besides, I don't need to do that, it should work
the way I'm doing it now. At least, this is how the reference does it.

Any help is appreciated.


I don't know what your programming problem is.

However, the reason that ROW_COUNT is 0 is that DB2 does not know the entire
number of rows in a select cursor until you fetch them (unless cursor
materialization is necessary to return the first row). In some cases,
depending on the isolation level, the answer set could change between the
first fetch and the last fetch.

DB2 does return to you the number of rows updated or deleted in an SQL
statement.

Nov 12 '05 #3
"Tarek M. Nabil" <Ta*********@itworx.com> wrote in message
news:c8**************************@posting.google.c om...
ROW_COUNT was just something I tried in my efforts to work around the
problem, and now according to this, it's obviously not the solution.

It would also help if DB2 had some variable that can tell me the row
number, like ROWNUM in Oracle. That could also be a work around.

But still, this is not the original problem, the original problem is
why the handler for SQLSTATE '02000' is called while there are still
rows left in the cursor.

There is a row number in DB2. Look at the "row_number () over" statement.

But I think it would be better to fix your program.
Nov 12 '05 #4
Thanks Mark.

I searched the SQL reference for DB2 for iSeries and there was no
mention of "row_number" or any other "row_something" except for
"row_count" which is in the "GET DIAGNOSTICS" command.

I totally agree with you that it would be better if I find out why
this is happening. I could put the whole stored procedure here, but it
would do nothing but complicate things. It's all just about the few
lines I posted and the problem is the continue handler for NOT FOUND
is getting called too early. I hope someone has seen this before and
is able to help.

Thanks again.

"Mark A" <ma@switchboard.net> wrote in message news:<f8******************@news.uswest.net>...
"Tarek M. Nabil" <Ta*********@itworx.com> wrote in message
news:c8**************************@posting.google.c om...
ROW_COUNT was just something I tried in my efforts to work around the
problem, and now according to this, it's obviously not the solution.

It would also help if DB2 had some variable that can tell me the row
number, like ROWNUM in Oracle. That could also be a work around.

But still, this is not the original problem, the original problem is
why the handler for SQLSTATE '02000' is called while there are still
rows left in the cursor.

There is a row number in DB2. Look at the "row_number () over" statement.

But I think it would be better to fix your program.

Nov 12 '05 #5
"Tarek M. Nabil" <Ta*********@itworx.com> wrote in message
news:c8**************************@posting.google.c om...
Thanks Mark.

I searched the SQL reference for DB2 for iSeries and there was no
mention of "row_number" or any other "row_something" except for
"row_count" which is in the "GET DIAGNOSTICS" command.

I totally agree with you that it would be better if I find out why
this is happening. I could put the whole stored procedure here, but it
would do nothing but complicate things. It's all just about the few
lines I posted and the problem is the continue handler for NOT FOUND
is getting called too early. I hope someone has seen this before and
is able to help.

Thanks again.

Sorry, I guess that I missed you mentioning you had DB2 for iSeries.
Nov 12 '05 #6
Tarek,

Are you sure that nothing in your mysterious "Do things here" section
below performs an UPDATE, SELECT or DELETE of zero rows? Any of those
would trigger a 02000 condition, causing your NOT_END flag to flip and
premature closure of the cursor.
Jeremy Rickard
WHILE (NOT_END <> 0) DO
FETCH cursorHoldings INTO var1, var2, (...and so on)
IF (NOT_END <> 0) THEN
/*
Do things here
*/
END IF;
END WHILE;

Nov 12 '05 #7
Jeremy,

This must be exactly what the problem is. I can't believe it never
crossed my mind. The thing is, I have to make those queries there.
You said there were workarounds?

jr******@unisystems.biz (Jeremy Rickard) wrote in message news:<d3**************************@posting.google. com>...
Tarek,

Are you sure that nothing in your mysterious "Do things here" section
below performs an UPDATE, SELECT or DELETE of zero rows? Any of those
would trigger a 02000 condition, causing your NOT_END flag to flip and
premature closure of the cursor.
Jeremy Rickard
WHILE (NOT_END <> 0) DO
FETCH cursorHoldings INTO var1, var2, (...and so on)
IF (NOT_END <> 0) THEN
/*
Do things here
*/
END IF;
END WHILE;

Nov 12 '05 #8
Ta*********@itworx.com (Tarek M. Nabil) wrote in message news:<c8**************************@posting.google. com>...
Jeremy,

This must be exactly what the problem is. I can't believe it never
crossed my mind. The thing is, I have to make those queries there.
You said there were workarounds?


"Workaround" was a poorly chosen word that implies a kludge, when the
solution is in fact perfectly clean. The trick is to remember that
declarations (including condition handlers) can be overridden in lower
levels of scope (BEGIN END blocks).

An example:

CREATE TABLE x(a INTEGER NOT NULL, b TIMESTAMP)@

INSERT INTO x(a)
VALUES
1, 2, 4, 5, 6@

CREATE PROCEDURE y()
LANGUAGE SQL
BEGIN
DECLARE v_at_end CHAR(1) DEFAULT 'N';
DECLARE v_a INTEGER;

-- No condition handler here - we leave the default handler
-- for 02000 in place, i.e. ignore not found conditions.

DECLARE c1 CURSOR FOR SELECT a FROM x;

OPEN c1;
WHILE v_at_end = 'N' DO
UPDATE x SET b = CURRENT TIMESTAMP WHERE a = v_a + 1;
BEGIN
-- Here's an override handler in the new scope level.
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
SET v_at_end = 'Y';

FETCH c1 INTO v_a;
END;
END WHILE;
END@

CALL y()@

SELECT * FROM x@

This returns:

A B
----------- --------------------------
1 -
2 2003-11-02-16.34.29.230001
4 -
5 2003-11-02-16.34.29.230003
6 2003-11-02-16.34.29.230004

5 record(s) selected.

Whereas written along the same lines as your procedure, we would exit
the cursor when it fails to update the non-existent row for key 3.
Jeremy Rickard
Nov 12 '05 #9
That doesn't work for me :(

Actually, I was surprised when I read it the first time because
(although I'm a newbie to both the DB2 and AS400 worlds) I remember
reading something in the SQL reference that really upset me at the
time, so it stuck in my mind.
It says:
"Notes
Compound statements cannot be nested."

I tried it anyways, and got the following error when creating the
procedure:

[SQL0777] Nested compound statements not allowed. Cause . . . . . :
Compound statements in the routine body of an SQL procedure or
function cannot be nested.

Are you sure this should work for DB2 on AS400? Maybe it works for
other versions of DB2? If not, is there any other way out of this?

Thanks for your continuous help.

jr******@unisystems.biz (Jeremy Rickard) wrote in message news:<d3**************************@posting.google. com>...
Ta*********@itworx.com (Tarek M. Nabil) wrote in message news:<c8**************************@posting.google. com>...
Jeremy,

This must be exactly what the problem is. I can't believe it never
crossed my mind. The thing is, I have to make those queries there.
You said there were workarounds?


"Workaround" was a poorly chosen word that implies a kludge, when the
solution is in fact perfectly clean. The trick is to remember that
declarations (including condition handlers) can be overridden in lower
levels of scope (BEGIN END blocks).

An example:

CREATE TABLE x(a INTEGER NOT NULL, b TIMESTAMP)@

INSERT INTO x(a)
VALUES
1, 2, 4, 5, 6@

CREATE PROCEDURE y()
LANGUAGE SQL
BEGIN
DECLARE v_at_end CHAR(1) DEFAULT 'N';
DECLARE v_a INTEGER;

-- No condition handler here - we leave the default handler
-- for 02000 in place, i.e. ignore not found conditions.

DECLARE c1 CURSOR FOR SELECT a FROM x;

OPEN c1;
WHILE v_at_end = 'N' DO
UPDATE x SET b = CURRENT TIMESTAMP WHERE a = v_a + 1;
BEGIN
-- Here's an override handler in the new scope level.
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
SET v_at_end = 'Y';

FETCH c1 INTO v_a;
END;
END WHILE;
END@

CALL y()@

SELECT * FROM x@

This returns:

A B
----------- --------------------------
1 -
2 2003-11-02-16.34.29.230001
4 -
5 2003-11-02-16.34.29.230003
6 2003-11-02-16.34.29.230004

5 record(s) selected.

Whereas written along the same lines as your procedure, we would exit
the cursor when it fails to update the non-existent row for key 3.
Jeremy Rickard

Nov 12 '05 #10
Ta*********@itworx.com (Tarek M. Nabil) wrote in message news:<c8**************************@posting.google. com>...
That doesn't work for me :(

Actually, I was surprised when I read it the first time because
(although I'm a newbie to both the DB2 and AS400 worlds) I remember
reading something in the SQL reference that really upset me at the
time, so it stuck in my mind.
It says:
"Notes
Compound statements cannot be nested."


The nested compounds definitely work on DB2 UDB for LUW, and IMHO are
an important feature of the language - but I was forgetting you were
on AS/400. I know very little about that flavour of DB2.

As a workaround I suppose you could try setting a flag to indicate
when you are doing a FETCH versus when you are doing anything else,
and change your original condition handler to only set AT_END = 'Y'
when in "fetch mode". Hope you see what I mean.

There may be better solutions that others can suggest.
Jeremy Rickard
Nov 12 '05 #11
This is a really good idea.

Unfortunately, data changes have caused the issue to stop happening.
I'm trying to replicate it but not with any success yet :((

Nevertheless, I have implemented the idea and it works syntactically.
I also think that if there was a chance this condition should happen
again, this would prevent it.

I would like to thank you for your continuous help and your brilliant
ideas :)

jr******@unisystems.biz (Jeremy Rickard) wrote in message news:<d3**************************@posting.google. com>...
Ta*********@itworx.com (Tarek M. Nabil) wrote in message news:<c8**************************@posting.google. com>...
That doesn't work for me :(

Actually, I was surprised when I read it the first time because
(although I'm a newbie to both the DB2 and AS400 worlds) I remember
reading something in the SQL reference that really upset me at the
time, so it stuck in my mind.
It says:
"Notes
Compound statements cannot be nested."


The nested compounds definitely work on DB2 UDB for LUW, and IMHO are
an important feature of the language - but I was forgetting you were
on AS/400. I know very little about that flavour of DB2.

As a workaround I suppose you could try setting a flag to indicate
when you are doing a FETCH versus when you are doing anything else,
and change your original condition handler to only set AT_END = 'Y'
when in "fetch mode". Hope you see what I mean.

There may be better solutions that others can suggest.
Jeremy Rickard

Nov 12 '05 #12
Jeremy Rickard wrote:
Ta*********@itworx.com (Tarek M. Nabil) wrote in message news:<c8**************************@posting.google. com>...
That doesn't work for me :(

Actually, I was surprised when I read it the first time because
(although I'm a newbie to both the DB2 and AS400 worlds) I remember
reading something in the SQL reference that really upset me at the
time, so it stuck in my mind.
It says:
"Notes
Compound statements cannot be nested."

The nested compounds definitely work on DB2 UDB for LUW, and IMHO are
an important feature of the language - but I was forgetting you were
on AS/400. I know very little about that flavour of DB2.


<snip>

Jeremy Rickard


I am informed that nested compound statements are supported by DB2 UDB
for iSeries (AS/400 follow-on) in V5R2. Reference:
http://publib.boulder.ibm.com/iserie...tm#HDRWHATSNEW

--
Karl Hanson

Nov 12 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

27
by: John Roth | last post by:
PEP 263 is marked finished in the PEP index, however I haven't seen the specified Phase 2 in the list of changes for 2.4 which is when I expected it. Did phase 2 get cancelled, or is it just not...
63
by: Martin Johansen | last post by:
Hey guys Since C is my language of choice for almost any kind of application, I'd like to know what the status of C is around the world today. And I am ofcourse not talking about C++ or C#. I...
2
by: mark | last post by:
I understand that writing programs with option strict on is the best way to obtain stable applications. I have also found the applications to run much faster. Option strict on disallows late...
8
by: Tim Reynolds | last post by:
Our .Net application calls a web method of aplpication 2 that resides on their Apache server. When I as a developer C#, Studios 2003, make the call to their web method from my desktop, I receive no...
7
by: Marek Zawadzki | last post by:
Hi all, In your opinion: what is current status of frameworks for PHP and which one would you choose? I am looking for an all-purpose, MVC-based framework I could learn and use for all the...
12
by: Stef Mientki | last post by:
In the example below, "pin" is an object with a number of properties. Now I want 1- an easy way to create objects that contains a number of these "pin" 2- an multiple way to access these "pin",...
3
ADezii
by: ADezii | last post by:
The process of verifying that an Object exists and that a specified Property or Method is valid is called Binding. There are two times when this verification process can take place: during compile...
0
by: Chris Calloway | last post by:
Just a reminder, we're at the two week warning on early bird registration for PyCamp: http://trizpug.org/boot-camp/2008/ Registration is now open for: PyCamp: Python Boot Camp, August 4 - 8...
0
by: ZitoMD | last post by:
I have an application where the user selects appropriate files from a OpenFileDialog box which then sends the file to the PDF printer. My problem is that I want to wait until there are no more...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.