AS/400开发经验点滴(七)
BLOG LIOU
十.在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的程序,就可以完成海量文件的分段并行处理。
示范程序源码如下:
[code:1:b06a0f6a54]
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
…………….[/code:1:b06a0f6a54]
2004.11.30
hsiang_wang 回复于:2004-11-30 13:19:16 |
好东西! |
qingzhou 回复于:2004-11-30 14:00:07 |
Very Good !
另外,我也借题发挥,针对文件相对记录号的话题做如下补充。 我们在文件中定义使用相对记录号处理文件,在一定的条件下,比如按顺序处理文件,存取速度很快。使用相对记录号文件应该在文件定义的第34列留空白。 下面再举2个例子解读CHAIN、使用相对记录号写文件的用法。 例1、从文件头至尾利用相对记录号对其进行CHAIN操作,最后显示文件记录总数: [code:1:9083a77897]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[/code:1:9083a77897] 例2、使用相对记录号写文件: [code:1:9083a77897]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 ......[/code:1:9083a77897] 备注:本例使用相对记录号将记录写入指定的位置上。 注意:只能将写入的记录放在原先已经删除的文件记录位置上,或者放置在使用INZPFM命令做过初始化操作的文件成员上。对于一个活动的文件记录,本操作无效。WRITE(E)的‘E’表示使用错误检验,%ERROR是错误检验内置函数。 如果不使用相对记录号,记录将被写入文件尾部。 显示文件的子文件存取方式就是利用相对记录号对文件进行操作的实例。 |
thursday 回复于:2004-11-30 14:19:41 |
是不是在写帐票或SUBFILE时经常用这个纪录号吧 |
blogliou 回复于:2004-11-30 14:40:27 |
qingzhou 补充得非常好啊!另外subfile确实也是用RRN来计算的。 |
fairyboy 回复于:2004-12-01 08:09:14 |
先提个小问题给楼主:怎么就看到AS/400开发经验1,2,3,4,然后一下子到7了,那个5和6那2个贴到哪去了呢?
都非常实用! |
Red_Crow 回复于:2004-12-01 08:50:08 |
guud! |
blogliou 回复于:2004-12-01 09:04:54 |
[quote:f064ae9287="fairyboy"]先提个小问题给楼主:怎么就看到AS/400开发经验1,2,3,4,然后一下子到7了,那个5和6那2个贴到哪去了呢?
都非常实用![/quote:f064ae9287] 5和6原来也发过,我刚才在坛上查了一遍,好象确实没有了?要不我重发一遍? |
╰●-●╯ 回复于:2004-12-01 09:22:04 |
感謝您,麻煩您重發一下5 & 6 ...3q ! ^^ |
thursday 回复于:2004-12-01 09:50:48 |
[quote:82c2f3eca4="blogliou"]
5和6原来也发过,我刚才在坛上查了一遍,好象确实没有了?要不我重发一遍?[/quote:82c2f3eca4] 行 |
blogliou 回复于:2004-12-01 09:53:28 |
“5”是讲一个通用日志管理工具的,有详细源代码,稍加包装就可以形成一个通用产品。斑竹删除或许是在保护我“知识产权”吧?^^
“6”是讲如何制作下拉菜单的。本坛上也有好多大虾对此也很有经验。 |
China_Free_Man 回复于:2004-12-01 10:21:38 |
高手!UP!!! |
Red_Crow 回复于:2004-12-01 11:40:50 |
想看5、6。 |
pl421 回复于:2004-12-01 16:40:43 |
是啊,想看5。6 |
bonbonben 回复于:2004-12-02 23:04:46 |
收获 |
rudy5 回复于:2004-12-04 09:55:53 |
谢谢,一直以来对RPG文件操作部分有很大的疑惑,现在又多了解了一点,非常感谢!还有关于文件操作的说明或是实例吗?不胜感激! |
albert55 回复于:2004-12-09 10:09:37 |
相对记录号没有那么好用,不信可以多试几种情况 |
yueh 回复于:2004-12-11 19:14:12 |
【重贴前帖】
AS/400开发经验点滴(一) http://bbs.chinaunix.net/forum/viewtopic.php?t=216871 AS/400开发经验点滴(二):一个批量修改文件属性的工具 http://bbs.chinaunix.net/forum/viewtopic.php?t=217254 AS/400开发经验点滴(三)--如何使用分布式关系数据库 http://bbs.chinaunix.net/forum/viewtopic.php?t=229798 AS/400开发经验点滴(四)--如何在程序中获取系统状态信息 http://bbs.chinaunix.net/forum/viewtopic.php?t=230540 AS/400开发经验点滴(五)-- 通用日志管理工具 http://bbs.chinaunix.net/forum/viewtopic.php?t=240545 AS/400开发经验点滴(六)--如何制作下拉菜单(源码) http://bbs.chinaunix.net/forum/viewtopic.php?t=257368 |
iced_edge 回复于:2004-12-12 23:32:41 |
好贴!谢谢楼主! |
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/