The issue is with the placement of return 0.
Here is a procedure against sample database to reproduce the issue:
(Please excuse the spacing... )
CREATE PROCEDURE USERID.STAFF_UPDATE ( )
SPECIFIC USERID.STAFF_UPDATE
LANGUAGE SQL
NOT DETERMINISTIC
CALLED ON NULL INPUT
MODIFIES SQL DATA
INHERIT SPECIAL REGISTERS
us: BEGIN
DECLARE sqlstate CHAR(5) DEFAULT '00000';
DECLARE sqlcode int default 0;
DECLARE a char;
DECLARE b char;
DECLARE sqltype char;
DECLARE c_query CURSOR WITH HOLD FOR
select p.PROJNO, p.PROJNAME
from PROJECT p, staff s
where s.id = cast(p.respemp as int)
order by s.dept;
DECLARE CONTINUE HANDLER FOR NOT FOUND
BEGIN
IF (sqltype = 'U') THEN
return 0;
END IF;
COMMIT;
END;
OPEN c_query;
FETCH FROM c_query INTO a, b;
While (sqlstate = '00000')
do
sqltype = 'U';
IF (a = 'MA2113') THEN
Insert into applog (Description) values ('Project identified
');
else
Insert into applog (Description) values ('valid projno = '||
char(a));
end if;
FETCH FROM c_query INTO a, b;
END WHILE;
END;
> > Failure occurs when creating the stored procedure... (prior to
> > running the stored proc)
[quoted text clipped - 9 lines]
> DB2 z/OS Utilities Development
> IBM Germany
> The issue is with the placement of return 0.
>
[quoted text clipped - 29 lines]
> COMMIT;
> END;
The problem is that RETURN is not a statement that counts as SQL-procedure
statement. Therefore, it cannot be embedded in a compound statement in an
exception handler. Besides, you state that your handler is a CONTINUE
handler, i.e. it does something and then _continues_ in the procedure. You
want to break that...
> OPEN c_query;
> FETCH FROM c_query INTO a, b;
[quoted text clipped - 14 lines]
> END WHILE;
> END;
If you look at the above logic, how about rephrasing it to:
FOR query_loop AS c_query
CURSOR WITH HOLD FOR
SELECT p.projno, p.projname
FROM project AS p, staff AS s
WHERE s.id = cast(p.respemp as int)
ORDER BY s.dept DO
INSERT INTO applog(description)
VALUES (CASE
WHEN p.projno = 'MA2113'
THEN 'Project identified'
ELSE 'valid projno = ' || CHAR(p.projno)
END);
END FOR
The loop will terminate when no record is found. Additionally, you don't
need the "sqltype", "a", and "b" variables and no handler for NOT FOUND
conditions. Even better yet, using a CASE expression instead of an IF
statement has the distinct advantage that DB2 can better optimize the
overall statement.
p.s: The variables "a" and "b" not speaking names. You should use names
that make it easy to understand what's going on.

Signature
Knut Stolze
DB2 z/OS Utilities Development
IBM Germany