从技术上讲,可能在 CL 中执行 SELECT;但它需要对 SQL CLI API 进行编码才能做到这一点。不适合没有经验且不值得努力的人。不过,CL 可以运行 INSERT 或 UPDATE 语句,然后使用 RCVF 检索插入的值。调用用 RPG、COBOL 或 C 编写的模块来执行 SQL 要容易得多。如果这些语言看起来遥不可及,那么 REXX 可以轻松执行 SQL 并将值传递给 CL。
没有 SQL,日期数学似乎是最好的。如果您想通过 CL 获得当月的“最后一天”,最简单的方法可能是设置为下个月的第一天并减去“1 天”。下面是一个使用一对CEE* Date and TIME APIs的例子:
pgm
dcl &fromDate1 *char 6
dcl &fromDate2 *char 8
dcl &resultDate *char 8
dcl &qyear *char 2
dcl &qmonth *char 2
dcl &rtnVal1 *int
dcl &rtnVal2 *int
dcl &picStr1 *char 6 value( 'YYMMDD' )
dcl &picStr2 *char 8 value( 'YYYYMMDD' )
rtvsysval sysval( QYEAR ) rtnvar( &qyear )
rtvsysval sysval( QMONTH ) rtnvar( &qmonth )
/* Set to a day near month-end... */
chgvar &fromDate1 ( &qyear *cat &qmonth *cat '28' )
callprc CEEDAYS ( +
&fromDate1 +
&picStr1 +
&rtnVal1 +
*omit +
)
/* Add enough days to guarantee in "next month"... */
chgvar &rtnVal2 ( &rtnVal1 + 4 )
callprc CEEDATE ( +
&rtnVal2 +
&picStr2 +
&fromDate2 +
*omit +
)
/* Set to 1st day of next month... */
chgvar %sst( &fromDate2 7 2 ) '01'
callprc CEEDAYS ( +
&fromDate2 +
&picStr2 +
&rtnVal1 +
*omit +
)
/* Subtract 1 day to get to "last day"... */
chgvar &rtnVal2 ( &rtnVal1 - 1 )
callprc CEEDATE ( +
&rtnVal2 +
&picStr2 +
&resultDate +
*omit +
)
/* Dump to show &resultDate is last-day of this month... */
dmpclpgm
return
endpgm
它首先将日期设置为当月的 28 日,然后添加 4 天。使用这些值可确保第一个计算日期始终在“下个月”之内。然后它获取该日期并将日期编号设置为“01”。从中减去“1 天”。
这两个 API 使用称为“Lilian day”的表示。这只是一个整数值,表示自 1582 年 10 月 14 日以来的天数。日期可以转换为 Lilian 天数,然后简单的整数数学可以添加或减去所需的天数。生成的整数可以转换回日期值。
您可以指定一个“图片字符串”来描述输入和输出日期的日期格式。我使用 6 字符格式作为初始输入,但使用 8 字符格式作为输出。您可以根据需要修改格式。最后,它只是简单地运行 DMPCLPGM 来显示结果。您可以设置一个 PARM() 变量以将结果返回给调用它的任何对象。
示例代码中的结果是当前月份的 LastDay。稍作改动,可以很容易地简化为返回下个月的第 3 天。
我考虑过在 SYSIBM.SYSDUMMY1 上创建一个表示 LAST_DAY(); 的视图但是,虽然 VIEW 在 SELECT 语句中运行良好,但它在 i 6.1 中使 RUNQRY 崩溃。尝试使它与 RCVF for CL 一起工作似乎不值得。
我还测试了添加一个在月末运行的虚拟作业调度程序条目。然后我使用适当的 API 从条目中检索 NextSubmissionDate。这工作得很好,但太晦涩难懂,不是一个好的解决方案。当然,如果整个目的是调度一个作业,那么简单地为它添加一个调度器条目可能就是应该做的。检索 NextSubmissionDate 只是将 LastDayOfMonth 放入任何 CL 程序的一种方式。
但如果这是目的,那么简单地拥有一个计算最后一天的 CL 模块是最直接的方法。