zoukankan      html  css  js  c++  java
  • AS/400开发经验点滴(七)在RPG程序中巧用相对记录号RRN

    十.在RPG程序中巧用相对记录号RRN

    1. RRN

    正像INFORMIX数据库有记录号ROWID,AS/400的PF文件的记录也都有一个隐含的记录号RRN。RRN是Relative-Record Number的缩写,也就是相对记录号,有时俗称记录“物理地址”。当向PF文件中增加记录时,每条记录都被赋上了一个RRN。在PF文件属性中有一个“Reuse deleted records”属性,表示是否重复使用删除记录的RRN,可以用CHGPF来修改该属性,如果该属性指定为*NO,那么新加的记录就只会追加到文件尾部,RRN号则顺序加1,如果删除一条记录,那么该条记录的RRN号仍会被保留,即记录空间不会被释放,那么文件就会一直增长,可以通过文件重组来重新排序RRN号。如果“Reuse deleted records”属性指定为*YES,那么被删除记录RRN号可以被重复利用,在新增加记录时,会优先查找以前是否有被删除的记录,如果有,就会把先前的RRN号赋给新增加的记录。

    同时,RRN还是SQL保留字,可以在SQL语句中使用,比如下例就可以看到RRN号:

    SELECT RRN(TESTPF), FLD1, FLD2, FLD3  FROM BLOG/TESTPF


    2. RPG中使用RRN

    在RPG程序中,同样可以使用RRN。巧用善用RRN,有时候还具有意想不到的效果。

    对没有键值的文件就可以根据相对记录号RRN,来连续或随机处理。RRN号也可以在SETLL、SETGT、CHAIN操作码中使用。要在RPG程序中使用RRN,必须在文件定义中指定RECNO关键词。RECNO关键词就表示DISK类文件是按照相对记录号(RRN)来处理的。RECNO可以在INPUT/UPDATE类文件上指定,提取的相对记录号会放在RECNO关键词括号内定义的一个字段内,该字段名可以自己定义,类型必须定义成数字类型,定义的长度应该足够放下提取的记录号长度。关键值RECNO和BLOCK(*YES)不能同时在同一个文件上定义。而且文件定义的34位必须为空,通常有键值的文件该位会被填K。使用了RECNO关键词,ILE RPG编译器不允许记录块读写(RECORD BLOCKING),但如果文件仅仅是输入文件,而且设置快速顺序访问(用OVRDBF指定SEQONLY(*YES)),那么块读写仍然被允许。 

    比如文件定义:

    FTESTPF    IF   E             DISK    RECNO(RRNO)

    定义字段RRNO:

    DRRNO                            9P 0 INZ(0)

    定义了相对记录号存放的RRNO字段后,就可以在RPG程序中使用相对记录号了。在读写每条记录时,都会返回该记录的RRN号。


    3.使用RRN优化处理大文件的例子

    下面举一例,看看如何使用RRN来优化处理大文件。假设有一个数据量为海量的大文件,需要对其顺序处理。通常我们会想到把该大文件拆分成若干小文件,然后对若干小文件进行并行处理。但把海量大文件拆分成若干小文件也需要耗去可观的时间,能不能不用对海量大文件进行拆分,就可以对该文件进行分段并行处理呢?使用RRN就可以做到。

    具体办法:
    (1) 首先在RPG程序的文件定义中定义RECNO关键词以及定义存放RRN号的字段。
    (2) 在RPG程序中指定分段的开始和结束RRN号。
    (3) 用开始RRN号和SETLL语句来定位分段的开始位置
    (4) 用读写记录返回的RRN号,来与分段结尾RRN号比较,当读写记录返回的RRN号大于分段结尾RRN号时,该段处理结束,程序返回。
    (5) 再编一个调用的RPG或CL的程序,指定若干个连续的分段,并用提交方式调用被调用的分段处理的RPG的程序,就可以完成海量文件的分段并行处理。

    示范程序源码如下:

         FTESTPF    IF   E             DISK    RECNO(RRNO)

         ………….

         DRRNO                            9P 0  INZ(0)

         ………….

         C     *ENTRY     Plist

         C                      Parm                    BEGNO            10 0

         C                      Parm                    ENDNO            10 0

         ………….

         C     BEGNO      SETLL    TESTPF

         C                      DOW     1=1

         C                      READ    TESTPF                                31

         C     *IN31        IFEQ      '1'

         C                      LEAVE

         C                      ENDIF

         ……………

        C                      IF        RRNO >; ENDNO

         C                      LEAVE

         C                      ENDIF

         ……………

         C                      ENDDO

         …………….


     
    2004.11.30

    ________________________________________

    另外,我也借题发挥,针对文件相对记录号的话题做如下补充。

    我们在文件中定义使用相对记录号处理文件,在一定的条件下,比如按顺序处理文件,存取速度很快。使用相对记录号文件应该在文件定义的第34列留空白。
    下面再举2个例子解读CHAIN、使用相对记录号写文件的用法。


    例1、从文件头至尾利用相对记录号对其进行CHAIN操作,最后显示文件记录总数:
    0001.00 ** Create by qingzhou  2004.11.30

    0002.00 **

    0003.00 FTEST_PF   IF    E             DISK     RECNO(RRN) ← 在关键字文件定义RECNO(RRN),RRN是相对记录号.

    0004.00 **

    0005.00 D RRN               S            9B 0   INZ(1)     ← D类定义一个变量RRN为9位16进制格式.

    0006.00 **

    0007.00 C       RRN          CHAIN     TEST_PF   ← 相对记录号索引文件TEST_PF(这里是升序).

    0008.00 C                    DOW       %FOUND(TEST_PF)

    0009.00 C                    EVAL      RRN=RRN+1

    0010.00 C       RRN          CHAIN     TEST_PF

    0011.00 C                    ENDDO

    0012.00 C**                                      ← 循环定义每读到一个记录将相对记录号+1,直到读到文件结束.

    0013.00 C                    EVAL      RRN=RRN-1 ← 将RRN-1,因为RRN最后的记数为记录数+1.

    0014.00 C       RRN          DSPLY ← DSPLY语句是将RRN显示在屏幕上,本语句在调试程序很有用。当语句执行DSPLY时,程序显示变量值,按执行键程序继续运行.

    0015.00 C**

    0016.00 C                    EVAL      *INLR=*ON


    例2、使用相对记录号写文件:
    0001.00 ** Create by qingzhou  2004.11.30

    0002.00 **

    0003.00 FTEST_PF   O    E             DISK     RECNO(RRN)

    0004.00 **

    0005.00 D RRN               S            9B 0   INZ(1)

    0006.00 **

    ......

    0009.00 C                    EVAL      RRN=RRN+1

    0010.00 C                    WRITE(E)  EMFMT  ← TEST_PF的记录格式名EMFMT

    0011.00 C                    IF        *ERROR

    0012.00 **                   Error processing

    0013.00 C                    ENDIF

    ......


    备注:本例使用相对记录号将记录写入指定的位置上。
    注意:只能将写入的记录放在原先已经删除的文件记录位置上,或者放置在使用INZPFM命令做过初始化操作的文件成员上。对于一个活动的文件记录,本操作无效。WRITE(E)的‘E’表示使用错误检验,%ERROR是错误检验内置函数。
    如果不使用相对记录号,记录将被写入文件尾部。

    显示文件的子文件存取方式就是利用相对记录号对文件进行操作的实例。

  • 相关阅读:
    【Anagrams】 cpp
    【Count and Say】cpp
    【Roman To Integer】cpp
    【Integer To Roman】cpp
    【Valid Number】cpp
    重构之 实体与引用 逻辑实体 逻辑存在的形式 可引用逻辑实体 不可引用逻辑实体 散弹式修改
    Maven项目聚合 jar包锁定 依赖传递 私服
    Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
    mysql案例~tcpdump的使用
    tidb架构~本地化安装
  • 原文地址:https://www.cnblogs.com/etsdpt/p/2317074.html
Copyright © 2011-2022 走看看