On 16-Oct-2015 17:24 -0500, Kendall Kinnear wrote:
I'm stumped by something a programmer brought up to me a little bit
ago. (5pm on Friday, just what I needed!)
I have an SQL statement that is coded as:
DATEG>=(left(cast(current_date as varchar(10)),4)
Seems a right-parenthesis was dropped; assumed that was there.
The casting from date-to-character, for intentions other than
displaying the result to humans [i.e. in computation\expressions],
*always* should be performed with the CHAR scalar casting function,
*never* the generic CAST scalar function.
That is because the CHAR scalar allows specifying the /format/ of the
resulting character string, whereas the CAST does not; specifically, the
CHAR casting scalar allows a second argument, in which a value such as
ISO, EUR, USA can be specified to ensure the desired format is effected
for the formatted date-string. The specified format is always the same
result-format, irrespective the SQL OPTION for DATFMT, whereas with the
CAST scalar, there is no argument to specify the DATFMT, and the
result-format is restricted to that of the SQL Date Format (DATFMT)
setting\OPTION established for that SQL /session/.
That statement works fine when I run the SQL statement using the
iNav run SQL function.
Presumably DATFMT=*ISO [or another of the 10-character, 4-digit-year
formats] is established for the result-format of date-string values.
When I try to run the same statement using RUNSQLSTM I get the
following which fails:
DATEG>=(left(Cast(Translate(Concat(Substring(Cast(CURRENT_DATE AS VarChar(10) CCSID37),1,4)
That is not the full message details, just a snippet of helpful
information that the database offered; an expansion of the expression
and predicate. The full details are [typically] required to be included
for the messaging, for a reader to properly assist in diagnosing the
problem. This issue however, is so common, and unlikely to be anything
else than...
For some reason RUNSQLSTM thinks it needs to translate CURRENT_DATE
to CCSID 37 and inserts the appropriate code.
The DATE data type is, given the high dependency on _character_
representations, is required to have a CCSID assigned, despite there may
seem no need; that is to suggest, that if the same rules applied to
numeric data, one might expect the numeric fields also would have to
have a CCSID assigned, but they do not. However the /editing/ feature
does have to have a CCSID. Date data type data however, ¿for reasons of
expediency and\or distaste by some for the concept of the EDIT
instruction? I do not know, but accept that that is a requirement. That
said, I there is almost zero chance of there being any relationship
between the CCSID casting and the issue being experienced.
I am very far from being an SQL expert so can someone point me in
the right direction?
The DDL was not given, nor the full message details of the msg
CPF5035 [or similar] that offered up the failing predicate. However
quite conspicuously, the column DATEG is at least a 4-digit numeric data
type. Because the DatFmt for the Run SQL Statement defaults to *JOB,
and the Date Separator (DATSEP) also defaults to *JOB, the
left-justified date-string formatted-result is in the form of *YMD,
*DMY, *MDY, or *JUL, for which every one of them will include a
*separator character* such as dash, slash, period, or comma. And while
either of the last two can be valid [because either character could
appear to be a valid decimal separator to the implicit
character-to-numeric casting function], that would depend on the
established Decimal Point (DECMPT) for the decimal separator used in
numeric literals\constants.
So if the DATFMT(*JOB) resolved to OPTION of DATFMT=*MDY and
DATSEP(*JOB) resolved to OPTION of DATSEP='/', then the attempt by the
database SQL to compute a result from the expression [in October between
10-Oct and 19-Oct inclusive] to assign to a a temporary operand
for the comparison to the value in the column named DATEG, that would
have failed. The failure would occur because the character expression
would have to be implicitly cast into numeric, from the character-string
value of '10/1'. But because the casting is not [also] an
expression-evaluator of the character-string result, that
character-string value can not be CAST into a numeric value because the
slash character is not a digit [nor a decimal separator]; the expression
using the CAST scalar fails to assign a value for comparison with the
numeric column DATEG.
The better expression, given the resultant value of the expression
should be the four-digit year value, would be to use the YEAR scalar [or
revise the expression to use CHAR and the argument to name the
date-format; here are both:
(YEAR(current_date)) /* place inside ZONE or DEC casting scalar to
explicitly specify matching data type and size to the DATEG column */
(left(char(current_date, ISO), 4)) /* ISO=='YYYY-MM-DD' */
As an Amazon Associate we earn from qualifying purchases.