|
Alan,
Not sure what was your problem.
First it was a code snippet with the focus on how to handle NULL values in
an embedded SQL RPG Program.
And second I added a comment (//Handle SQL Error) where to handle an SQL
error.
I could have included another check after the OPEN, but If the OPEN fails,
the FETCH will fail, too.
If you already want to include an error handling, than do it correctly.
If you want to check the SQL State, have check the status group (the first
2
characters) and not the complete SQLSTATE (may be in exceptions).
If the first 2 characters are 00 than everything is ok, that does not mean
it must be always 00000.
If the first 2 characters are 01 than a warning occurs. That means data is
returned, but something should be considered (for example SQLSTATE 01503 -
The number of result columns is larger than the number of variables
provided.)
If the first 2 characters are 02 than no record is returned.
All other status groups mark an SQL Error.
From the IBM i Knowledge Center:
The class code of an SQLSTATE value indicates whether the SQL statement was
executed successfully (class codes 00 and 01) or unsuccessfully (all other
class codes).
For checking an SQL Error, I prefer the SQLCODE because it is easier to
check for < *Zeros and = 100, than substringing the SQLSTATE.
Instead of throwing an Dummy SQL Message, I'd suggest to trap the real SQL
Error Message. ... whether you want add the SQLSTATE or not is your
decision.
DCL-S LocErrMsg VarChar(256);
...
If %Subst(SQLSTATE: 1: 2) <> '00'
and %Subst(SQLSTATE: 1: 2) <> '01'
and %Subst(SQLSTATE: 1: 2) <> '02';
Exec SQL Get Diagnostics Condition 1 :LocErrMsg = MESSAGE_TEXT;
YourErrorMsgHandling(%Trim(LocErrMsg) + ' ' + SQLSTATE);
End-If;
We even check the SQLCODE in the SQL Error Handling Procedure. If an error
occurred an escape message is sent, otherwise the procedure is left
immediately.
Mit freundlichen Grüßen / Best regards
Birgitta Hauser
"Shoot for the moon, even if you miss, you'll land among the stars." (Les
Brown)
"If you think education is expensive, try ignorance." (Derek Bok)
"What is worse than training your staff and losing them? Not training them
and keeping them!"
„Train people well enough so they can leave, treat them well enough so they
don't want to.“ (Richard Branson)
-----Original Message-----
From: RPG400-L <rpg400-l-bounces@xxxxxxxxxxxx> On Behalf Of Alan Campin
Sent: Sonntag, 18. März 2018 23:56
To: RPG programming on the IBM i / System i <rpg400-l@xxxxxxxxxxxx>
Subject: Bad Code Alert
Brigitta, this is not a personal attack on you. I see this error all over
the place at my company and I keep trying to get it stopped.
Recently the following code snippet was presented.
Exec SQL Declare CsrC01 cursor for
Select TS1, VarChar1, TS2, Decimal1
From ...
Where ...;
Exec SQL Open CsrC01;
DoU 1=0;
Exec SQL Fetch Next From CsrC01
into :LocTS1 :LocTS1Ind, :MyVarChar1,
:LocTS2 :LocTS2Ind, :MYDec1;
If SQLCODE = 100
or SQLCODE < *Zeros;
//Handle SQL Error;
Exec SQL Close CsrC01;
Leave;
EndIf;
This code represents a severe problem. The problem. No SQL error checking.
It is absolutely critical that SQL statement be error checked. If an error
occurs on a File I/O, an error is thrown but unless the error is critical
the only thing that happens in SQL is that an error code is returned in
SQLSTATE (I use SQLSTATE. SQLCODE can also be used).
This is all that happens. If an SQL error is not checked the program will
simply continue on. I cannot tell you the number of times that I have gone
into SQL programs running in production that I determined where failing
and
had been failing for years. The effect from those errors was minor to
severe.
The above code should look like the following.I am using my standard error
handler for these examples because it throws an exception message and stops
processing. . Note that I have no error checking on Declare. It does not
generate any machine code and does not need to be error checked.
dcl-c SQL_STATE_NO_ROW '02000';
dcl-c SQL_STATE_OK '00000';
Exec SQL Declare CsrC01 cursor for
Select TS1, VarChar1, TS2, Decimal1
From ...
Where ...;
Exec SQL Open CsrC01;
If SqlState <> SQL_STATE_OK;
// Report error and stop processing.
XVERRH_Throw('CPF9898':
CPF_MESSAGE_FILE_NAME:
'Open Cursor CsrC01 Failed! SqlState = ' + SqlState); EndIf;
DoU 1=0;
Exec SQL Fetch Next From CsrC01
into :LocTS1 :LocTS1Ind, :MyVarChar1,
:LocTS2 :LocTS2Ind, :MYDec1;
Select;
When SqlState = SQL_STATE_NO_ROW;
Exec SQL Close CsrC01;
Leave;
When SqlState = SQL_STATE_OK;
// process record.
Other;
// Report error and stop processing.
XVERRH_Throw('CPF9898':
CPF_MESSAGE_FILE_NAME:
'Fetch Next From CsrC01 failed! Sql State = ' +
SqlState);
EndSl;
EndDo;
I want to emphasize again the importance of stopping processing. If an
error
occurs, we must stop processing. If we continue, we are just compounding
the
problem.
Please note also that I am stopping processing for both warning and
errors.It has been my experience that warning error are always masking some
form of programming error and need to be investigated.
I appreciate their may be certain rare condition were we want processing to
continue after a warning but they are the exception.
I again apologize if I have hurt anyone feeling but I felt it was important
to bring this to the groups attention. SQL error checking is absolutely
critical.
--
This is the RPG programming on the IBM i (AS/400 and iSeries) (RPG400-L)
mailing list To post a message email: RPG400-L@xxxxxxxxxxxx To subscribe,
unsubscribe, or change list options,
visit: https://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives at
https://archive.midrange.com/rpg400-l.
Please contact support@xxxxxxxxxxxx for any subscription related
questions.
Help support midrange.com by shopping at amazon.com with our affiliate
link:
http://amzn.to/2dEadiD
--
This is the RPG programming on the IBM i (AS/400 and iSeries) (RPG400-L)
mailing list
To post a message email: RPG400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: https://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at https://archive.midrange.com/rpg400-l.
Please contact support@xxxxxxxxxxxx for any subscription related
questions.
Help support midrange.com by shopping at amazon.com with our affiliate
link: http://amzn.to/2dEadiD
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.