显示加载了已排序数据库记录的子文件

时间:2012-08-12 07:13:23

标签: ibm-midrange rpgle rpg

比方说,我有这些表:

USRMF(主要物理文件)

User ID   User Name  
A00001    SAMUEL
A00002    ADAM

USRTS

user id   date   time in    time out
A000001   080812 084555     104545 
A000001   080812 120800     150000
A000001   080812 170000     180000
A000001   090812 084555     104545
A000001   090812 170000     180000
A000002   080812 084555     104545 
A000002   080812 120800     150000
A000002   080812 170000     190000
A000002   090812 084555     104545
A000002   090812 170000     190000

我的子文件应该看起来像这样:

Option:  5-display

OPT   User ID   User Name  Date   TimeIn  TimeOut
 _    A000001   SAMUEL     090812 084555  180000
 _    A000002   ADAM       090812 084555  190000
 _    A000001   SAMUEL     080812 084555  180000
 _    A000002   ADAM       080812 084555  190000

*此子文件显示每个用户的摘要数据&天: 第一次进入和最后一次出去。该名称应该从其他数据库表(USRMF)中读取,并且应该按时间卡日期排序。

如果用户将选项5放在第三个子文件行上, 其中用户ID:A000001用户名:samuel和日期090812,  然后将显示到下一个子文件屏幕。

OPT   User ID   User Name  Date   TimeIn  TimeOut
 _    A000001   SAMUEL     080812 084555  104545 
 _    A000001   SAMUEL     080812 120800  150000
 _    A000001   SAMUEL     080812 170000  180000

此子文件应列出当天和所选人员的所有时间和超时时间。

我应该怎么做这个程序?????????特别是对于第一个子文件。?????

2 个答案:

答案 0 :(得分:4)

数据库

首先,任何DBA都会告诉您,如果您是从头开始创建,请不要使用DDS来定义您的文件。从长远来看,如果用SQL定义它们会更好,如下所示:

    CREATE TABLE USERMAST
      (UserID     char(7),
       UserName   char(25)
      );
    LABEL ON TABLE  USERMAST is 'User Master Table';

    CREATE TABLE WORKPERIOD
      (UserID     char(7),
       WorkDay    date,
       StartTime  time,
       EndTime    time
      );
    LABEL ON TABLE  WORKPERIOD is 'User Work Periods';

请注意,这是使用实际数据和时间字段,而不是数字字段。这使得根据需要更容易操作。运行SQL时,可以指定日期和时间格式的首选项,例如* ISO,* DMY或* EUR。您可以将其视为以ISO ISO格式存储,但以您希望的任何格式提供给您。

无论您的文件(表格)是否已在DDS或SQL中定义,您仍应使用嵌入式SQL来读取程序中的数据。起初,它看起来可能比本机I / O更复杂。但是当你了解它时,你会发现它更强大,更容易,更快速,更灵活。

处理

嵌入SQL的基本概念实际上并不复杂。你的程序在自由格式的ILE RPG中可能是这样的(假设你正在使用它):

       EXEC SQL      DECLARE CURSOR c1 FOR your-select-statement;
       EXEC SQL      OPEN c1;
                     do while SQLSTATUS is ok;
       EXEC SQL        FETCH FROM c1 INTO :var1, :var2, ... ;
                       if SQLSTATUS is ok;
                         // process data
                       endif;
                     enddo;
       EXEC SQL      CLOSE c1;

检查SQLSTATE的前两个字符,检查数据结束或其他问题。 '00'表示一切正常,'01'是警告(可能不行),其他一切都是错误。 (这比使用SQLCODE更容易。)

您在DECLARE CURSOR语句中放置了一个SELECT语句(更具体地说是一个完整选择),它确定了当您从游标进行FETCH时系统将为您提供的内容。 SELECT可以做很多有力的事情。在这里,它将从两个表中获取信息并为您汇总行。如果您只是总结,可能如下所示:

    SELECT userid, workday, min(starttime) as firsttime, max(endtime) as lasttime
      FROM workperiod
      GROUP BY userid, workday

如果您只是从两个表中加入数据,它可能如下所示:

    SELECT u.userid, u.username, p.workday, p.starttime, p.endtime
      FROM UserMast as u
      JOIN WorkPeriod as p  on u.userid = p.userid

把这些放在一起的首选方法是这样的:

    WITH s as
    ( SELECT userid, workday, min(starttime) as firsttime, max(endtime) as lasttime
      FROM workperiod
      GROUP BY userid, workday
    )
    SELECT u.userid, u.username, s.workday, s.firsttime, p.lasttime
      FROM UserMast   as u
      JOIN WorkPeriod as p  on u.userid = s.userid
      ORDER BY workday descending, username
      FOR INPUT ONLY

有关使用SQL访问数据库的更多信息,请参阅IBM i Information Center。查看数据库/参考。有关显示文件的信息,请在编程/ DDS / DDS下的信息中心中查看显示文件,


显示文件

就显示文件而言,您需要为每个子文件屏幕定义至少两种记录格式 - 子文件记录格式和子文件控制记录格式。

子文件记录用于列表中的一行。它应该有SFL关键字。

子文件控制记录管理屏幕。它通常包含子文件的屏幕标题和列标题。它应该有SFLCTL(yoursubfilename)SFLSIZ(subfile-rows)SFLPAG(rows-per-page),nn SFLDSP,nn SFLDSPCTL,nn SFLCLR,nn SFLEND(*MORE),其中nn代表一种调节指标。您通常希望指定子文件行比每页行数多1个。此处还包括任何功能键规格。

您可能还需要屏幕底部的记录格式,以告诉用户可以使用哪些功能键。如果是这样,请在子文件控制记录中使用OVERLAY关键字。

处理

1。)关闭SFLDSPSFLDSPCTL,以防止它们暂时显示在屏幕上。打开SFLCLR以启用创建空子文件。现在写下子文件控制记录。

2.。)在循环中处理来自数据库的行,增加子文件记录号,并写入子文件记录。

3。)完成子文件记录填写后:打开SFLDSPSFLDSPCTL,以便显示两者。关闭SFLCLR,这样就不会消除子文件记录。打开SFLEND,使其在每页底部显示“更多...”,除了最后一页。写下你的立足点记录。 EXFMT你的子文件控制记录。处理任何适用的功能键。

答案 1 :(得分:0)

@WarrenT提供了一个很好的答案,即使您不喜欢SQL,也可以使用一般概念来加载和显示子文件。我们大多数人学到的方式是通过一本名为Application Display Programming指南的旧书。它在15年内没有改变。除此之外,我强烈建议你让一位同事告诉你小组其他人如何进行子文件编程。几乎可以肯定你想要符合风格问题。