![]() | |
![]() |
| | Thread Tools | Display Modes |
#11
| ||||
| ||||
|
|
On 29-Nov-2011 15:33 , TheBoss wrote: CRPence<CRPence (AT) vnet (DOT) ibm.com> wrote: On 29-Nov-2011 09:08 , Graham Hobbs wrote: A given date less than current date... Really? I know the example was taken almost directly from a prior offered link, but that is some very specific logic included in an apparent attempt merely to "validate" a[n unspecified bounds] date string. No, it is just a clever way to validate that a certain variable is a valid date (or time or datetime); boundaries are not relevant at all. I understand the concept. The chosen statement however, implies something different to anyone who might review\read the coded SQL; even with a visibly coded response to any SQL errors that might follow the EXEC SQL. That was my point.... per "Really?", as in, why use something so confusing? |
|
The SYSIBM.SYSDUMMY1 view isn't a real table/view, but a dummy one that resides in memory and makes it possible to perform arithmetic using special registers like "CURRENT_DATE" (and "CURRENT_TIME" / "CURRENT_TIMESTAMP") in SQL. The DB2 for i provides and uses the actual TABLE, as does DB2 for z from what I recall./ |
|
/Though given that description, I infer that perhaps some DB2 might just rewrite such SELECT INTO statements as a VALUES INTO instead, which could conceptually be described in the same way.? Interesting, but I have never seen any documentation to support that effect. The DB2 for i I know [and AFaIK still] performs the actual query of the TABLE when\as requested, but no longer uses a dummy table [or view] to implement the VALUES INTO statement several years and releases earlier. |
|
In this case it is not even relevant which specific computation is done, as long as it (implicitly) contains a comparison of the host-variable to be validated with a variable/value known to be a correct date, time or datetime. Yep. That is why the DATE() [cast] scalar of a 10-byte character string could do the same. And without any comparison to, nor any reason to evaluate, the CURRENT DATE special register. This comparison fails on a syntax-error (SQL-code "-181" in DB2 for zOS) when the host-variable isn't a valid date (or time or datetime). This means that the OP should catch the error (as said: -181 for DB2 zOS, not sure about LUW, but this should be easy to find out). Just seemed to me that anyone asking such novice questions about the SQL would not be so clear about both ignoring the result [in the host variable] and deferring to the SQLstate because SQLSTATE values would be consistent due to standards; noting the reference above, to SQLcode instead.? This is also where using the comparison is ugly IMO, since a valid date can effect one of two results for SQLcode\SQLstate, either non-zero or zero. A valid date can effect either an SQLcode=100 [for a valid date of today or future] or the SQLcode=0 [for any valid past date] along with the selected integer value updated\into the host variable. I would expect that someone asking such basic questions about the SQL might just add a [presumably wrong\undesirable] test like "SQLcode<>0" after the SELECT INTO. Similarly, the SQLstate. Even if using SELECT versus VALUES INTO, dropping the WHERE clause entirely would IMO be much prettier for a general validation. Using a statement like either of SELECT DATE(:CharDate) INTO or SELECT DAYS(:CharDate) INTO, each eliminates the confusing predicate and gives either a valid result with a zero sqlcode\sqlstate or an error; plus, AFaIK, an indicator variable could be used instead\additionally to test validity, something which is not a consistent option for the "SELECT 1" for the same variations on effects for the :HV. The first error suggests the dummy table usage is unnecessary; i.e. the VALUES INTO can be used instead. <<SNIP The reason for using SYSIBM.SYSDUMMY1 is that it is compatible between platforms (at least for DB2 zOS vs. DB2 LUW, not sure about DB2/400). I'm not so sure this is true for VALUES and the DAYS- and DATE- functions. The VALUES INTO statement and those scalars exist for every member of the DB2 family according to any [even several years old] documentation I have seen. |
#12
| |||
| |||
|
|
here's some reasons for my doubt on using the VALUES solution in a z/OS environment: |
#13
| |||
| |||
|
|
On 2011-11-29 18:08, Graham Hobbs wrote: [...] .. so using one of the refs you pointed to, in my COBOL pgm I issue .. EXEC SQL SELECT 1 FROM SYSIBM.SYSDUMMY1 WHERE :ADATE < CURRENT_DATE END-EXEC. .. and the compile says .. SQL0029N INTO clause required. Explanation: Non-cursor SELECT or VALUES statements embedded in an application program must have an INTO clause to denote where the results of the statement are to be placed. Dynamic SELECT statements do not permit the INTO clause. User response: Add the INTO clause to the SELECT or VALUES statement and precompile the application program again. .. so I change the WHERE clause to .. WHERE :ADATE < CURRENT_DATE INTO SYSIBM.SYSDUMMY1 Just guessing, but shouldn't that be: EXEC SQL SELECT 1 INTO :A_VARIABLE FROM SYSIBM.SYSDUMMY1 WHERE :ADATE < CURRENT_DATE END-EXEC. ? /Lennart ------ |
#14
| |||
| |||
|
|
On Tue, 29 Nov 2011 19:12:59 +0100, Lennart Jonsson erik.lennart.jonsson (AT) gmail (DOT) com> wrote: On 2011-11-29 18:08, Graham Hobbs wrote: [...] .. so using one of the refs you pointed to, in my COBOL pgm I issue .. EXEC SQL SELECT 1 FROM SYSIBM.SYSDUMMY1 WHERE :ADATE < CURRENT_DATE END-EXEC. .. and the compile says .. SQL0029N INTO clause required. Explanation: Non-cursor SELECT or VALUES statements embedded in an application program must have an INTO clause to denote where the results of the statement are to be placed. Dynamic SELECT statements do not permit the INTO clause. User response: Add the INTO clause to the SELECT or VALUES statement and precompile the application program again. .. so I change the WHERE clause to .. WHERE :ADATE < CURRENT_DATE INTO SYSIBM.SYSDUMMY1 Just guessing, but shouldn't that be: EXEC SQL SELECT 1 INTO :A_VARIABLE FROM SYSIBM.SYSDUMMY1 WHERE :ADATE < CURRENT_DATE END-EXEC. ? /Lennart ------ Folks, Thankyou for the help. From the CICS screen where users can change any field, I have edit paragraphs. If ALL the edits are valid then EXEC SQL UPDATE DTTS SET ADATE = :ADATE ,ATIME = :ATIME .. missed a couple of fields ,TOTAL_CARS = :TOTAL-CARS ,TCHA = :TCHA WHERE CURRENT OF DTTS_U1_KYA END-EXEC else return error msg about the highest error on the screen to the user. Because my pgm will run on different platforms and different DB2's and given what I am hearing/reading about 'differences', I've concluded that it is better to change the logic of the pgm so that date, time and timestamp -180 etc tests get done as a consequence of the above SQL while all the other edits will precede it. Is fractionally untidy in that edits are now in two areas of the pgm. Unforutnately depending on where fields are on screen, if ADATE and TCHA are in error, if ADATE is higher on screen, TCHA will be the error msg the user receives (screen only has 1 msg line) - in other words the user will not get the highest error msg first. Hope I'm making sense here! Again thanks for the help, I learned much. Graham .. after I penned and before posting the above, I see more posts .. you guys are so way above my league:-) --- |
#15
| |||
| |||
|
|
On Wed, 30 Nov 2011 22:54:44 -0500, Graham Hobbs wrote: From the CICS screen where users can change any field, I have edit paragraphs. If ALL the edits are valid then EXEC SQL UPDATE DTTS SET ADATE = :ADATE ,ATIME = :ATIME .. missed a couple of fields ,TOTAL_CARS = :TOTAL-CARS ,TCHA = :TCHA WHERE CURRENT OF DTTS_U1_KYA END-EXEC else return error msg about the highest error on the screen to the user. Because my pgm will run on different platforms and different DB2's and given what I am hearing/reading about 'differences', I've concluded that it is better to change the logic of the pgm so that date, time and timestamp -180 etc tests get done as a consequence of the above SQL while all the other edits will precede it. Is fractionally untidy in that edits are now in two areas of the pgm. Unfortunately depending on where fields are on screen, if ADATE and TCHA are in error, if ADATE is higher on screen, TCHA will be the error msg the user receives (screen only has 1 msg line) - in other words the user will not get the highest error msg first. Hope I'm making sense here! Well - choke on that idea :-( Waiting for the -180 thru -187 from the above UPDATE is fine except when there are two or more of these DTTS (date, time, timestamp) columns - how can I tell which one or more has gone wrong |
|
so .. back to what has been suggested before. Hope I can make it work. .. |
|
suppose I could use separate UPDATE SQL's. |
#16
| |||
| |||
|
|
On 01-Dec-2011 19:41 , Graham Hobbs wrote: On Wed, 30 Nov 2011 22:54:44 -0500, Graham Hobbs wrote: From the CICS screen where users can change any field, I have edit paragraphs. If ALL the edits are valid then EXEC SQL UPDATE DTTS SET ADATE = :ADATE ,ATIME = :ATIME .. missed a couple of fields ,TOTAL_CARS = :TOTAL-CARS ,TCHA = :TCHA WHERE CURRENT OF DTTS_U1_KYA END-EXEC else return error msg about the highest error on the screen to the user. Because my pgm will run on different platforms and different DB2's and given what I am hearing/reading about 'differences', I've concluded that it is better to change the logic of the pgm so that date, time and timestamp -180 etc tests get done as a consequence of the above SQL while all the other edits will precede it. Is fractionally untidy in that edits are now in two areas of the pgm. Unfortunately depending on where fields are on screen, if ADATE and TCHA are in error, if ADATE is higher on screen, TCHA will be the error msg the user receives (screen only has 1 msg line) - in other words the user will not get the highest error msg first. Hope I'm making sense here! Well - choke on that idea :-( Waiting for the -180 thru -187 from the above UPDATE is fine except when there are two or more of these DTTS (date, time, timestamp) columns - how can I tell which one or more has gone wrong GET DIAGNOSTICS might help. And effectively forces use of SQLSTATE instead of the less desirable SQLCODE, which should probably be done anyhow.? so .. back to what has been suggested before. Hope I can make it work. .. Other than validation being performed separately, then performed again [but presumably never failing] in the UPDATE, the approach both seems reasonable and should be available\functional as a SELECT INTO or VALUES INTO. suppose I could use separate UPDATE SQL's. The UPDATE WHERE CURRENT OF could be repeated for each SET; i.e. against each column in whatever order is desired.? With each UPDATE the code would know which one column gave rise to a data error. One alternative that, like the original idea allows moving the validation to where desirable, might involve something like... The validation of multiple values could be moved into SQL stored procedure routine(s) where an OUT [or INOUT] parameter could identify the first in-error, of several ordered IN parameters that are to be validated: exec sql call tst_parms(:whichInParmIsBad, :adate, :atime, ...) As probably less desirable alternatives, the validation might be able to be moved into CHECK CONSTRAINTS which are added with names that identify the column. Or moved into an UPDATE TRIGGER routine which provides custom diagnostics. Either or both could protect the TABLE from activity outside the application. Or TRIGGER routine(s) established on an identical twin\sibling TABLE which is used only for a means to perform validation, could disallow all I\O activity and identify specific column value errors with custom diagnostics, without any impact to I\O on the original TABLE. Regards, Chuck --- |
#17
| |||
| |||
|
|
Isn't the individual UPDATE method inefficient? |
|
That said I would not be expecting too many programs having reams of DTTS columns if ANY. Reason I say this is I expect to receive DCLGEN's from folk and generate pgms therefrom. Is important for me to have 'things right'. Am consoled that DTTS are likely low usage columns and even if present are likely not required to be updatable - gotta be prepared though. |
|
Will think more of your other ideas although starting to look too complex .. if I send pgms to people simplicity has to be the norm. |
#18
| |||
| |||
|
|
On 02-Dec-2011 19:33 , Graham Hobbs wrote: Isn't the individual UPDATE method inefficient? Yes, multiple UPDATE Table SET Column=:HV WHERE CURRENT OF versus just one UPDATE with multiple SET requests surely is inefficient. But inefficient relative to what instead, and as compared to the ease of implementing in some other fashion, are both valid considerations. That was mentioned only as an affirmative response to the comment supposing "I could use separate UPDATE SQL" statements\requests; i.e. not necessarily a recommendation. That said I would not be expecting too many programs having reams of DTTS columns if ANY. Reason I say this is I expect to receive DCLGEN's from folk and generate pgms therefrom. Is important for me to have 'things right'. Am consoled that DTTS are likely low usage columns and even if present are likely not required to be updatable - gotta be prepared though. I have never so tightly coupled a database operation to interaction with a screen [none that I can recall anyhow], nor have I used multiple UPDATE versus just one against a FETCHed row; I can not be sure how much of an impact the multiple UPDATEs would be, on any of the DB2 variants, other than to know the row lock would be held longer and logging presumably 'larger'. IMO just doing one of the VALUES INTO or SELECT INTO wherever validation is already being done on the other non-DTTS inputs, is probably the best implementation; my preference being the former. Recall that in response to "back to what has been suggested before. Hope I can make it work" I responded with that "approach both seems reasonable and should be available\functional as a SELECT INTO or VALUES INTO." Though I alluded that the WHERE clause could be eliminated, and that testing the SQLSTATE is [according to DB2 documentation] more appropriate than testing the SQLCODE. Will think more of your other ideas although starting to look too complex .. if I send pgms to people simplicity has to be the norm. If there were specific requirements [none have been stated AFaIK] about the Date\Time\Timestamp formats [e.g. ISO-only, thus disregarding any localization preferences for internationalization of the app] on inputs, then there are very efficient and simple algorithms to validate the character strings as dates [without the SQL]. The actual elements of DTTS are very specific and limited; e.g. the element of year is 1 to 9999, of month 1 to 12, and of day 1 to 31 for some months or 1 to 30 for some other months or 1 to 28 for one month depending on the year in which 29 might be allowed: https://groups.google.com/d/msg/it.c...I/W6Uem90pLjcJ I did not look at the .cbl sources TheBoss made reference-to in an earlier reply, but I would expect they should be so simple, if there was a known [limited set of] formatting for the inputs.? Recomposed as an ISO date string after validation, would ensure no error on the SET for the UPDATE. Regards, Chuck ------ |
)
#19
| |||
| |||
|
|
3. One problem I've just hit is that much of the chat on this topic has been lost because my NewsReader doesn't keep them long enough - is OK have made some notes. |
|
I followed your ref (thru the Spanish too!), made for some deep reading. |
![]() |
| Thread Tools | |
| Display Modes | |
| |