3.2 存取方式服务设施(Access Method Services)

VSAM之前的数据管理需要许多实用例程做数据集的内部管理。

IEBGENER:复制顺序数据集的内容。

IEHMOVE和IEBCOPY:复制、移动、改编、扩展、备份和恢复分区数据集的内容。

IEBISAM:装载、备份、恢复和改编ISAM数据集的内容。

对于VSAM来讲,只有一个例程,却能完成所有VSAM所需的内部管理,该内部管理例程是IDCAMS,它也由它提供的功能而得名。该服务功能为存取方法服务(Access Method Services),或简称AMS。

执行实用程序的基本JCL是:

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //DELDEF   EXEC PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=*
        000005 //SYSIN   DD   *
        000006     /* UTILITY COMMAND STATEMENTS */
        000007 /*
        000008 //

AMS命令语句有一些功能,需要附加DD语句,但SYSPRINT和SYSIN语句总是必需的。有许多方法构成AMS提供的多种服务功能,在这显示的功能新的系统可能需要它们,例如,第1个任务是建立用户目录和数据空间的,这是建立VSAM文件所需的步骤。

3.2.1 语句的语法

AMS命令格式基本上是自由形式,类似于REXX或PL/1。语句的默认位置是从第2列到第72列,任何命令语句可以从当前行延续到下一行,只要在最后一个参数后加上连接符(-);延续一个值的连接符是(+);命令语句中可以嵌入注解,用注解符/* 和*/括起来;空行可以出现在AMS命令之前,中间或之后。位置参数是必需的,必须出现在关键字参数之前;关键字参数可以是独立的,可以是相关的一组值,或用圆括号括起来的一组子参数列表。参数、子参数和值之间彼此用空格、逗号或注解块分开来。

执行一次IDCAMS例程可以包含多个AMS命令,从而实现多个功能。因此,AMS为每个命令设定了返回码,同时每次执行IDCAMS例程时,系统会维护一个最大的返回码。在命令执行期间,AMS提供检查返回码的机制,并以前一步的返回码为判断基础,有条件地执行命令语句。

AMS设定的返回代码解释如下。

● 0——正常结束。功能命令完成,处理成功。

● 4——小错误。处理可以继续进行,但发生了小错误,系统会发送警告信息。

● 8——较大的错误。处理可以继续进行,但发生了比较大的错误,主要命令可能跳过不执行。

● 12——逻辑错误。通常是设定了不一致的参数,使整个命令跳过不执行。

● 16——严重错误。像这种严重错误发生,不仅命令不能完成,整个AMS命令流也会忽略掉。

以返回代码值为判断基础的有条件执行命令的语句结构是IF-THEN–ELSE结构。

在IF语句里,返回代码是作为LASTCC或MAXCC之一来设定的,LASTCC指的是在命令执行期间由正好在IF结构之前的AMS命令设定的返回代码,MAXCC则是在整个IDCAMS执行期间出现的最大返回码值。设定的操作符解释如表3.1所示。

表3.1 IF语句的操作符及其含义

接下来的THEN关键字或ELSE关键字,无论是单个AMS命令还是AMS命令块,都须包含成对的DO/END进行编码。如果在IF-THEN-ELSE结构里THEN关键字或ELSE关键字没有跟随AMS功能命令,或在下一行没有包含功能命令的续行符,就设定了一个空的THEN或ELSE语句。SET命令用来设定LASTCC值或MAXCC的值,SET命令经常用来重新设定一些警告错误信息的返回码为0。

3.2.2 定义用户目录

定义用户目录命令的语法格式如下。注意,这里通过去掉某些高级可选项以达到简化语法图的目的。

由于VSAM目录拥有它所居住的整个卷,因此VSAM目录必须是第1个存储在卷上的VSAM实体。当定义VSAM目录时,AMS自动定义卷上的数据空间,并分配数据空间给VSAM目录,对索引和数据部分可以指定个别的空间分配子参数。一般来说如果只给目录分配空间,就不需要为索引和数据部分指定个别空间子参数,将整个数据空间(由AMS自动生成的)全部分配给目录。在这种情况下,需要使用个别的AMS功能命令去定义一个或多个目录所拥有的空间,以便将来在空间里建立VSAM实体。如果已编码了个别索引和数据部分空间分配子参数,一般情况下目录的SPACE参数定义了建立数据空间的大小,并且为数据和索引部分指定的SPACE子参数决定了分配给目录的数据空间,剩余的数据空间将分配给其他的VSAM实体。大多数情况下,对目录而言一个柱面(cylinder)的空间就足够了。

下面的作业流定义两个用户目录——UCDMTP06定居在3390设备的DMTP06卷内和UCDMTP08定居在3390设备的DMTP08卷上。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS   EXEC PGM=IDCAMS,REGION=4096K
        000004 //SYSPRINT DD  SYSOUT=A
        000005 //DMTP06   DD  UNIT=3390,VOL=SER=DMTP06,DISP=OLD
        000006 //DMTP08   DD  UNIT=3390,VOL=SER=DMTP08,DISP=OLD
        000007 //SYSIN   DD  *
        000008   DEFINE USERCATALOG (                                   -
        000009                NAME (UCDMTP06)                           -
        000010                VOLUME (DMTP06)                           -
        000011                TRACKS (13259 0)                          -
        000012                FOR (9999) )                              -
        000013          DATA (TRACKS (15 5) )                           -
        000014          INDEX (TRACKS (15) )
        000015
        000016   IF LASTCC = 0 THEN                                     -
        000017         LISTCAT ALL CATALOG(UCDMTP06)
        000018
        000019   DEFINE USERCATALOG (                                   -
        000020               NAME (UCDMTP08)                            -
        000021               VOLUME (DMTP08)                            -
        000022               TRACKS (15)                                -
        000023               FOR (9999) )
        000024
        000025   IF LASTCC = 0 THEN                                     -
        000026        LISTCAT ALL CATALOG(UCDMTP08)
        000027
        000028 /*
        000029 //

这个作业流的SYSOUT的名字为IBMUSERA。建立两个目录之间的差别,是如何去使用选项DATA上的空间分配参数,和怎样利用INDEX部分去定义两个目录,以及如何在单个选项里预留有效的数据空间。

3.2.3 定义数据空间

定义数据空间命令的语法格式为:

通过定义新的VSAM实体(Object)的DEFINE语句中指定UNIQUE参数,可以隐含定义数据空间。这样系统就会分配所需要的空间给该实体自己使用。从数据管理的角度来看,通常最好是分配整个直接存取存储卷作为VSAM数据空间,然后通过子分配为新定义的实体分配空间。DEFINE SPACE AMS命令的目的是分配数据空间,并将其置于用户目录的控制。

下面的作业流是利用卷DMTP08上的有效空间去定义数据空间,它受前一个作业流里定义的用户目录UCDMTP08的控制。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS   EXEC PGM=IDCAMS,REGION=4096K
        000004 //SYSPRINT DD  SYSOUT=A
        000005 //DMTP08   DD  DISP=OLD,UNIT=3390,VOL=SER=DMTP08
        000006 //SYSIN   DD  *
        000007
        000008   DEFINE SPACE (                                      -
        000009                TRACKS(11688)                             -
        000010                VOLUMES(DMTP08)                           -
        000011                FILE(DMTP08)                              -
        000012                )                                         -
        000013              CATALOG(UCDMTP08)
        000014
        000015   IF MAXCC = 0 THEN DO                                   -
        000016        LISTCAT ALL CATALOG(UCDMTP08)                    -
        000017     END
        000018 /*
        000019 //

3.2.4 定义别名

当需要目录搜索时,有几种方式可以使VSAM做出决定应使用哪一个目录,一个是为已存在的实体定位目录项目,另一个是为一个新实体创建目录入口。绝大多数的AMS命令通过在命令里加入CATALOG参数,就可以明确地指出使用哪一个目录,而在命令里加入CATALOG参数的方法,其优先权大于任何其他方法。另一个可以明确定义使用目录的方式是在作业的JCL里加入JOBCAT和/或STEPCAT DD语句。如果以上方法都不使用,AMS将利用目标的高级限定符或数据集名,去确定所搜寻的目录。如果高级限定符与用户目录相匹配,将使用用户目录,否则使用主目录。

定义别名(Defining an Alias)命令的语法格式为:

以下的作业流将定义与前面定义的两个用户目录有关的两个别名。它们简单地把由用户目录控制的直接存取存储设备的序列号与目录连接起来,即将前面定义的两个用户目录与对应的磁盘卷对应起来。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS   EXEC PGM=IDCAMS,REGION=4096K
        000004 //SYSPRINT DD  SYSOUT=A
        000005 //SYSIN   DD  *
        000006
        000007   DEFINE ALIAS (NAME(DMTP06)                            -
        000008                 RELATE(UCDMTP06) )
        000009
        000010   DEFINE ALIAS (NAME(DMTP08)                            -
        000011                 RELATE(UCDMTP08) )
        000012
        000013   IF MAXCC = 0 THEN DO                                   -
        000014         LISTCAT ALIAS                                    -
        000015     END
        000016
        000017 /*
        000018 //

3.2.5 定义VSAM文件

定义VSAM文件(DEFINE CLUSTER)命令的语法格式如下所示。注意,由于去掉了某些高级参数,所以下面的语法图已得到简化。

使用DEFINE CLUSTER命令可以定义VSAM文件的所有3种类型:键顺序文件、进入顺序文件和相对记录文件。命令的语法是复杂的,有些参数可能永远不会一起使用,而许多参数也只是用来覆盖某些高级选项的,但通常我们建议你直接使用系统提供的默认值。

可以指定的主要参数列表是由按照CLUSTER、DATA和INDEX 3部分归类的。指定在CLUSTER中的参数适用于整个文件,而指定在DATA部分的参数则指定DATA部分有效,同样地,指定在INDEX部分的参数只对INDEX部分有效。几乎所有可以指定给CLUSTER的参数,也可以指定在DATA和INDEX部分。只有定义键顺序文件的时候才会有INDEX部分。就个人经验而言,经常指定在DATA和INDEX部分的参数只有NAME一项,否则AMS将为文件的DATA和INDEX部分生成奇怪(不容易理解)的名字。在生产环境里,为DATA和INDEX分别指定不同参数的另一个原因,是为了提高系统运行的性能。文件的DATA和INDEX部分可以分开放到不同的直接存取存储卷上。

现在对定义VSAM文件的参数做一个说明。

● 空间分配。

指定文件需要的空间大小,可以编码下面的3个空间分配子参数之一。

✧ 柱面(Cylinders)。

✧ 磁道(Tracks)。

✧ 记录(Records)。

其任何一种都可以用做首次和第2次分配空间大小的单位。首次分配空间是文件的初始空间,第2次分配用于当有效的空间已经用尽,而还有附加的记录要加入到文件中时进行附加空间的分配。文件基于几个因数,可以按照第2次分配空间大小的倍数进行几次扩展,但不能多于123次。当AMS将计算分配给文件的直接存取存储设备的有效空间时,首选使用RECORD分配方式。

VOLUMES参数指定一个或多个直接存取存储设备卷,其上面的空间将分配给文件。分配空间通过设定UNIQUE /SUBALLOCATION参数来决定,如果设定UNIQUE,在指定的VOLUMES上必须存在自由空间;在卷上建立独立的数据空间,全部分配给文件。从数据管理的角度来看,通常这不是一个好的建议,最好的方法是,允许AMS从已经定义的VSAM数据空间中进行再分配。

● 文件类型。

你可以使用下面的3个参数定义你的VSAM文件的类型。

✧ INDEXED代表键顺序文件(KSDS)。

✧ NONINDEXED表示进入顺序文件(ESDS)。

✧ NUMBERED表示相对记录文件(RRDS)。

● 记录大小。

RECORDSIZE参数表示写入到文件中的逻辑记录的大小,包括定长和变长记录。如果指定的平均值和最大值是相等的,则写入到文件中的记录是定长的;如果平均值和最大值不同,记录就是变长的,记录大小不能超过最大值。

● 记录键(只对KSDS文件有效)。

KEYS参数指定记录里主键的长度和位置(与记录的起始位直有关,0表示第1个字符)。

● 重复使用。

REUSE参数允许文件定义为可以被重新设置为空状态,而不用删除或重新定义。

下面的参数都是可选的,一般来说,你可以为你的文件选择它们的默认值。

● 缓冲区大小。

BUFFERSPACE用于指定处理数据集所需的缓冲区大小的最小值,其值将影响控制间隔大小,AMS通常选择空间足够大的缓冲区,可以放得下两个控制间隔和一个索引记录作为缓冲区的初始值。不管在这里编码的值是什么(或默认),这个值都可以通过JCL参数在执行时覆盖。

● 控制间隔大小。

大多数情况下,CONTROLINTERVALSIZE参数是省略的,这就允许AMS去选择更有效的值用于数据集。一个控制间隔范围可以是从512到32,768字节。如果大小在512和8,192字节之间,应指定512的倍数。如果在8,192和32,768字节之间,应指定2,048的倍数。如果大小不是适当值的倍数,AMS将调解大小直到等于下一个适当的倍数。如果为KSDS的INDEX部分指定CONTROLINTERVALSIZE,大小必须是512、1,024、2,048、4,096。

● 清除。

要删除文件时,使用ERASE参数,文件所占用的空间会用二进制数的0覆盖掉,原来文件的内容会被物理清除以后再重新使用。

● 自由空间(只对KSDS文件)。

FREESPACE参数代表了尚未分配空间的百分比,以便将来扩展用。此百分比适用于当记录初始装载到文件中和当由于记录被插在已存在的记录之间,导致控制间隔和控制区域分裂时,作为插入记录的空间。如果没有指定FREESPACE,控制间隔将被尽可能地填满,不留一点儿空间给未来要加入的记录。

● 复制和嵌入(只对KSDS文件)。

REPLICATE表示VSAM应将索引记录尽可能多次地写到磁道(Track)上。而IMBED则表示索引文件的顺序集记录要嵌入到文件的数据部分。当顺序集嵌入到数据部分时,VSAM就会将顺序集写到相关控制区域的第1个磁道内,IMBED自动隐含REPLICATE选项。当没有指定IMBED选项时,索引部分的顺序集与索引的其他部分存放在一起。REPLICATE和IMBED的使用可以在增加存储容量的前提下,提高系统运行的性能。

● 模板。

MODEL参数表示用已存在文件的属性复制到新定义的文件中。当使用MODEL时,所需附加的参数只有NAME。如果附加参数由MODE指定,它将首先从已存在的文件中复制属性到新数据集中。

● 预先格式化空间。

SPEED/RECOVERY参数用来在定义文件(DEFINE)的处理过程中指定是否要对给文件分配的空间预先做格式化。指定RECOVERY(默认值)导致系统将所分配空间以文件结束标志(End-of-File)填充。如果初始装载数据时失败了,我们可以利用文件结束标志从断点开始重新装载。对于大的数据集,这就可以节省恢复的时间,但是,代价是你在定义文件时必须将所有的字节用文件结尾标志填满。SPEED表示定义文件时,不用写文件结束标志,这样可以加快文件定义的速度。

下面的作业流定义的是我们后面使用的交易文件的KDSD版本,即键顺序的文件。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //DEFTRAN  EXEC PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=*
        000005 //SYSIN   DD   *
        000006   DELETE IBMUSER.TEST.BKTRAN.KSDS.CLUSTER
        000007   SET MAXCC=0
        000008   DEFINE CLUSTER (NAME(IBMUSER.TEST.BKTRAN.KSDS.CLUSTER) -
        000009                   VOL(DMTOS1) -
        000010                   IXD KEYS(04 0) -
        000011                   RECSZ(80 80)  -
        000012                   SPEED IMBED REPLICATE -
        000013                   NOREUSE SHAREOPTIONS(3 3) ) -
        000014          DATA   (NAME(IBMUSER.TEST.BKTRAN.KSDS.DATA) -
        000015                   CONTROLINTERVALSIZE(32760) -
        000016                   CYL(01,01) ) -
        000017          INDEX   (NAME(IBMUSER.TEST.BKTRAN.KSDS.INDEX) -
        000018                   CONTROLINTERVALSIZE(512) -
        000019                   TRACKS(10,10) )
000020 /*

作业流的SYSOUT是IBMUSERA。现在对该文件的控制语句做以下说明。

● 第6行的DELETE语句首先删除同名的VSAM文件,以防止数据集的重复。

● 第7行的SET语句将最大返回码MAXCC设置为0。这是我们经常采取的办法,避免由于要删除的文件不存在而导致的返回码大于0的情况。总之,第6行和第7行的两条语句通常一起配合使用,达到的目的是,如果文件存在就删掉它,如果不存在,删除不成功也没有关系,反正MAXCC都会置成0。

● 第8行到第19行是我们定义VSAM文件DEFINE CLUSTER的完整命令。第8行首先为我们的VSAM文件取的名字为IBMUSER.TEST.BKTRAN.KSDS.CLUSTER。

● 第9行的VOLUME(缩写为VOL)指定VSAM文件占据的磁盘卷为DMTOS1。

● 第10行的INDEXED(缩写为IXD)表明我们建立的文件为键顺序文件,即KSDS。这一行的另一个参数KEYS(4,0)定义KSDS文件的关键字,它的起始位置为0,即记录的第1个字节,长度为4,这样交易文件的关键字就是我们的交易日志号了。

● 第11行的RECORDSIZE(缩写为RECSZ)定义记录长度,其中,前面的数字80表示平均长度,后面的数字80表示最大长度,当二者相同时,表示文件为定长记录,反之则是变长记录。在我们的例子中,文件记录是定长80个字节的。

● 第12行有3个参数,它们都有各自的含义。其中,REPLICATE和IMBED的使用可以以空间换时间,即在增加存储容量的前提下,提高系统运行的性能;而SPEED参数则可以加快文件定义时的处理速度,因为不用人为地将所有分配给文件的空间用文件结尾标志填满。

● 第13行的NOREUSE表明文件不能置为空,换句话说,只有先删除(DELETE)再重新定义(DEFINE)才能将文件清空。

● 第13行的另外一个选项SHAREOPTIONS,我们在前面已做了专门的讲解,这里选的是(33)表明文件具有完全的共享性,读和写的完整性要由应用系统来保证。

● 第14行和第17行通过为DATA和INDEX部分指定NAME参数,使得我们很容易看出在目录列表中文件这两个部分的关系。

● 第15行和第18行分别为DATA部分和INDEX部分指定了不同的CI大小,这是根据文件的性质决定的。

● 第16行和第19行分别为DATA部分和INDEX部分分配了不同的空间,这是根据业务的需求计算出来的。

下面的作业流定义进入顺序(ESDS)文件。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //DEFTRAN  EXEC PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=*
        000005 //SYSIN   DD   *
        000006   DELETE IBMUSER.TEST.BKTRAN.ESDS.CLUSTER
        000007   SET MAXCC=0
        000008   DEFINE CLUSTER (NAME(IBMUSER.TEST.BKTRAN.ESDS.CLUSTER) -
        000009                   VOL(DMTOS1) -
        000010                   NONINDEXED  -
        000011                   RECSZ(80 80)  -
        000012                   SPEED IMBED REPLICATE -
        000013                   NOREUSE SHAREOPTIONS(3 3) ) -
        000014          DATA   (NAME(IBMUSER.TEST.BKTRAN.ESDS.DATA) -
        000015                   CONTROLINTERVALSIZE(32760) -
        000016                   CYL(01,01) )
        000017 /*

作业流的SYSOUT是IBMUSERA。现在对定义文件的控制语句做以下说明。

● 由于我们定义的是ESDS文件,所以,原来第10 行的INDEXED(缩写为IXD)变成了现在的NONINDEXED(可以缩写为NIXED),表明我们建立的文件为进入顺序文件,即ESDS。原来这一行的另一个参数KEYS(4,0)也不需要了,因为ESDS文件不需要定义关键字。

● ESDS文件只有数据(DATA)部分,没有索引(INDEX)部分,所以原来定义索引部分的语句也消失了。

● 其他语句与索引文件一样,这里就不重复了。

下面的作业流定义相对记录文件。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //DEFTRAN  EXEC PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=*
        000005 //SYSIN   DD   *
        000006   DELETE IBMUSER.TEST.BKTRAN.RRDS.CLUSTER
        000007   SET MAXCC=0
        000008   DEFINE CLUSTER (NAME(IBMUSER.TEST.BKTRAN.RRDS.CLUSTER) -
        000009                   VOL(DMTOS1) -
        000010                   NUMBERED   -
        000011                   RECSZ(80 80)  -
        000012                   SPEED IMBED REPLICATE -
        000013                   REUSE SHAREOPTIONS(3 3) ) -
        000014          DATA   (NAME(IBMUSER.TEST.BKTRAN.RRDS.DATA) -
        000015                   CONTROLINTERVALSIZE(32760) -
        000016                   CYL(01,01) )
        000017
        000018   IF LASTCC = 0 THEN
        000019     REPRO INDATASET(IBMUSER.TEST.BKTRAN) -

作业流的SYSOUT是IBMUSERA。现在对定义文件的控制语句做以下说明。

● 由于我们定义的是相对RRDS文件,所以原来第10行的NONINDEXED(可以缩写为NIXED)变成了现在的NUMBERED(可以缩写为NUMD),表明我们建立的文件为相对记录文件,即RRDS。相对记录文件也不需要关键字字段。

● RRDS文件与ESDS文件一样,只有数据(DATA)部分,没有索引(INDEX)部分。

● 这里我们使用了REUSE参数,这样,在不用删除文件的情况下就可以将其置为空文件。

● 其他语句与索引文件一样,这里就不重复了。

3.2.6 装载记录到VSAM文件中

下面是装载(REPRO)记录到VSAM文件中的命令的语法格式。

虽然在实际的生产环境下,装载初始记录到VSAM文件中可能需要用COBOL、PL/1或汇编语言编写的程序,但实际上我们经常使用AMS REPRO命令来达到此目的。在以后的章节里将会看到如何使用REPRO命令达到其他的目的,但这里的目标是把另一个数据集里的原始数据初始装载到VSAM文件中。

只需要两个参数,一个用来指定输入数据集(要被装载的原始数据文件),另一个就是要被装入的输出文件。通过INFILE或INDATASET参数设定输入数据集,当使用INFILE时,记录从DD语句设定的NAME参数中读取,DD语句必须在JCL中说明与其NAME相匹配的文件。当使用INDATASET时,系统通过搜寻相匹配的VSAM目标来找到输入文件。

接收输入文件记录的VSAM文件由OUTFILE或OUTDATASET指定,OUTFILE指定JCL里DD语句所定义的目标文件,而OUTDATASET指定目标VSAM文件要从VSAM目录中查找。

现在对定义VSAM文件的参数做以下说明。

● 指定装载记录的起始位置。

✧ FROMKEY指定复制操作起始点记录的键值,FROMKEY只适用于KSDS输入数据集。

✧ FROMADDRESS指定复制操作起始点记录的RBA值,FROMADDRESS只适用于KSDS输入数据集和ESDS数据集。

✧ FROMNUMBER指定复制操作起始点的记录相对记录号,FROMNUMBER只适用于RRDS输入数据集。

✧ SKIP用来指定在复制操作开始之前需要跳过的输入数据集记录个数。

● 指定装载记录的结束位置。

✧ TOKEY指定复制操作结束记录的全键值或部分键值,TOKEY只适用于KSDS输出文件。

✧ TOADDRESS指定复制操作结束记录的RBA值,TOADDRESS只适用于KSDS或ESDS输出文件。

✧ TONUMBER指定复制操作结束记录的相对记录号,TONUMBER只适用于RRDS输出文件。

✧ COUNT参数可以指定复制到输出文件的记录个数,当指定的记录个数达到时,复制操作就会结束。

● 覆盖数据集中已有的记录。

装载数据时,如果输出数据集里的记录与输入数据集里的记录重复时,REPLACE短语会自动将输出文件里已存在的记录覆盖掉。REPLACE适用于KSDS和RRDS文件,REPLACE也可以用来合并来自不同输入数据集的记录。REPRO操作的输入记录可以与随后要再次装载的输入文件有相同的记录,如果它们要装载到同一目标数据集时,必须使用REPLACE选项使得后面装载的输入记录可以覆盖目标数据集中已有的记录。如果要增加一条重复的记录,而又没有使用REPLACE选项,就会出现错误的信息,输入记录也将被丢掉。重复记录发生4次时,系统会终结REPRO操作,输入文件的剩余记录将不再继续处理。

● 重设输出文件为空。

在装载开始之前,指定REUSE参数将导致输出文件重设为空状态。如果REPRO时指定REUSE参数,输出文件必须在定义其CLUSTER时指定REUSE属性。

下面的作业流将顺序文件格式的用户交易日志文件装载到索引文件格式的交易日志文件中。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //REPRO1   EXEC PGM=IDCAMS
        000004 //SYSPRINT DD SYSOUT=*
        000005 //IN1     DD DSN=IBMUSER.TEST.BKTRAN,DISP=SHR
        000006 //OUT1    DD DSN=IBMUSER.TEST.BKTRAN.KSDS.CLUSTER,DISP=SHR
        000007 //SYSIN   DD *
        000008   REPRO INFILE(IN1)  -
        000009         OUTFILE (OUT1)
        000010         REPLACE
        000011 /*

作业流的SYSOUT是IBMUSERA。我们在定义文件时没有指定REUSE属性,但是在REPRO命令上指定了REPLACE参数,这就导致输出文件中的记录如果与输入数据集中的记录键值相同,就会被覆盖掉。提交此作业两次可以看到:注意在目录列表里的DATA部分之下,总共被处理的记录数是97,接收和被更改的记录数也是97, 这代表第2次提交作业后,来自输入数据集里的记录数与已存在的输出文件里的记录数相同。

3.2.6.1 使用REPRO备份文件

REPRO命令除了可以用来装载数据到VSAM文件中外,也可以用来备份VSAM文件的内容。下面的作业流将索引文件IBMUSER.TEST.BKTRAN.KSDS.CLUSTER的内容备份到磁盘的QSAM文件上。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //REPRO1   EXEC PGM=IDCAMS
        000004 //SYSPRINT DD SYSOUT=*
        000005 //IN1      DD DSN=IBMUSER.TEST.BKTRAN.KSDS.CLUSTER,DISP=SHR
        000006 //OUT1     DD DSN=IBMUSER.TEST.BKTRAN.BKUP1,
        000007 //         DISP=(NEW,CATLG),
        000008 //         SPACE=(TRK,(3,2),RLSE),
        000009 //         DCB=(RECFM=FB,LRECL=80,DSORG=PS)
        000010 //SYSIN   DD *
        000011   REPRO INFILE(IN1)  -
        000012         OUTFILE (OUT1)
        000013 /*

下面的作业流将把KSDS文件IBMUSER.TEST.BKTRAN.KSDS.CLUSTER的内容复制到另一个KSDS文件IBMUSER.TEST.BKTRAN.KSDS.BKUP.CLUSTER中。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //DEFTRAN  EXEC PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=*
        000005 //SYSIN   DD   *
        000006   DELETE IBMUSER.TEST.BKTRAN.KSDS.BKUP.CLUSTER
        000007   SET MAXCC=0
        000008   DEFINE CLUSTER (NAME(IBMUSER.TEST.BKTRAN.KSDS.BKUP.CLUSTER) -
        000009                   VOL(DMTOS1) -
        000010                   MODEL(IBMUSER.TEST.BKTRAN.KSDS.CLUSTER)) -
        000011          DATA   (NAME(IBMUSER.TEST.BKTRAN.KSDS.BKUP.DATA)) -
        000012          INDEX   (NAME(IBMUSER.TEST.BKTRAN.KSDS.BKUP.INDEX))
        000013
        000014   IF LASTCC = 0 THEN
        000015     REPRO INDATASET(IBMUSER.TEST.BKTRAN.KSDS.CLUSTER) -
        000016           OUTDATASET(IBMUSER.TEST.BKTRAN.KSDS.BKUP.CLUSTER)
        000017
        000018   IF LASTCC = 0 THEN
        000019     LISTCAT ALL LEVEL(IBMUSER.TEST.BKTRAN.KSDS)
        000020
        000021 /*
        000022 //

作业流的SYSOUT是IBMUSERA。REPRO的目标文件首先被删除掉,然后再定义,使用MODEL参数来复制原始KSDS文件的属性。如果在实际确实使用了此策略,最好把备份文件再定义一次,同时因为文件是用来做备份的,还需定义REUSE属性。然后REPRO命令能够使用REUSE参数在复制操作之前重设备份数据集为空,这样可以节省每次的删除和重定义时间。

3.2.6.2 从备份文件中恢复数据

从使用REPRO命令备份文件中恢复VSAM文件的内容,如果没有定义REUSE属性,就要首先删除原来的VSAM文件,然后重定义文件,以确保文件中已存在的记录确实被备份文件中的记录替代。完成这项工作可以执行原来的备份作业流,不过需要将原来的备份文件作为输入数据集,而将原来的VSAM文件作为输出数据集。

3.2.7 建立VSAM文件的可移植备份

EXPORT命令用来创建VSAM文件的可携带或可移植的备份,供你移植到其他的主机上。当使用REPRO命令复制文件时,只有VSAM文件的数据记录写入输出数据集中。如果你想恢复文件中的建立,必须通过执行AMS DEFINE命令重建文件。

EXPORT命令所建立的备份,则包含重建文件需要的所有信息,而不需要额外执行DEFINE命令。这种可携带的备份必须包含在非VSAM的顺序数据集中。

EXPORT命令的语法格式为:

注意这里EXPORT命令没有CATALOG参数,除非目标文件的入口是在主目录里,或目标名的第1个限定符包含目标的用户目录的别名,否则在你的JCL语句中必须包含JOBCAT或STEPCAT DD语句。

当执行具有PERMANENT(默认值)选项的EXPORT时,如果文件的便携式副本建立成功,AMS将删除原始的目标文件。默认情况下,影响删除功能的文件属性,在REPORT命令执行时将控制删除处理。如果文件指定了ERASE属性,在删除之前文件的所有记录被重写成二进制值0。在EXPORT命令上指定ERASE/NOERASE选项可以覆盖VSAM文件定义时设定的属性。如果原来的VSAM文件的保留期还没有到期,将不能执行删除操作。在EXPORT命令上指定PURGE/NOPURGE选项可以覆盖原始文件的保留状态。

指定INHIBITSOURCE参数表示在EXPORT命令执行成功后,原始文件变为“只读”状态。同样,指定参数INHIBITTARGET表示所建立的便携式备份也是“只读”的。

下面的作业流将建立相对记录文件IBMUSER.TEST.BKTRAN.RRDS.CLUSTER的临时复制文件在磁盘上。注意已经指定备份文件为CATLG,并且备份数据集名的高层限定符是IBMUSER,磁盘数据集将被编目在与原始VSAM文件所在的同一个用户目录上。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS  EXEC PGM=IDCAMS,REGION=4096K
        000004 //BACKUP   DD  DSN=IBMUSER.TEST.BKTRAN.EXPORT,
        000005 //         SPACE=(TRK,(3,3),RLSE),
        000006 //         UNIT=SYSDA,DISP=(NEW,CATLG,DELETE)
        000007 //SYSPRINT DD  SYSOUT=A
        000008 //SYSIN    DD  *
        000009
        000010   EXPORT IBMUSER.TEST.BKTRAN.RRDS.CLUSTER                 -
        000011          OUTFILE(BACKUP)                               -
        000012          TEMPORARY
        000013
        000014 /*
        000015 //

作业流的SYSOUT是IBMUSERA,因为在EXPORT命令上指定了TEMPORARY,原始文件在建立了它的便携式副本后仍然会保留下来。

3.2.8 恢复VSAM文件的可移植备份

由EXPORT命令建立的顺序数据集只能用IMPORT命令处理,这相当于恢复原始文件。AMS首先搜寻输入文件名相同的入口目标目录,如果入口不存在,AMS将使用含有便携式副本的目录信息去定义新目录入口,然后重新装载目标。如果目录入口存在,AMS核实入口,是否是前一个具有TEMPORARY选项的EXPORT命令定义为输出的入口。如果情况属实,AMS假设文件已经从前一个输出复制中恢复;AMS删除旧的目标,用EXPORT副本里的目录信息定义新目录入口,重新装载目标。如果目录入口存在,但却不是前一个EXPORT所标志的备份,IMPORT命令就会失败。IMPORT命令的语法格式为:

请注意,这里简化的语法图去掉了某些高级的可选参数。如果已编目的非VSAM数据集包含了便携式副本,可以使用INDATASET参数处理输入。

下面的作业流将刚刚做的磁盘上的便携式副本恢复到相对记录文件IBMUSER.TEST.BKTRAN.RRDS. CLUSTER中。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS  EXEC PGM=IDCAMS,REGION=4096K
        000004 //BACKUP   DD  DSN=IBMUSER.TEST.BKTRAN.EXPORT,DISP=OLD
        000005 //OUT1    DD  DSN=IBMUSER.TEST.BKTRAN.RRDS.CLUSTER,DISP=OLD
        000006 //SYSPRINT DD  SYSOUT=A
        000007 //SYSIN    DD  *
        000008
        000009   IMPORT INFILE(BACKUP)   -
        000010          OUTFILE(OUT1)    -
        000011          INTOEMPTY        -
        000012          PURGE
        000013
        000014 /*
        000015 //

作业流的SYSOUT是IBMUSERA。由于要恢复的VSAM文件IBMUSER.TEST.BKTRAN.RRDS. CLUSTER已经存在,所以,我们必须指定第11行的INTOEMPTY参数,告诉系统我们现在是将可移植备份恢复到一个已存在的空VSAM文件中。

除用做备份以外,EXPORT和IMPORT命令也可以用来把VSAM文件从一个计算机系统移到另一个中。IMPORT命令为此目的特别设置了几个参数选项。

OBJECTS参数指定输入备份文件的原始名,你可以建立一个新名和更改目标卷,这些参数会覆盖原来包含在便携式副本中的内容。恢复文件的其他属性可以通过ALTER命令来更改,少数几个属性,包括空间分配和一些影响执行性能的属性可以更改。如果需要更改这些属性,需定义具有所需属性的空文件,并指定INTOEMPTY参数,INTOEMPTY参数表示便携式副本已输入到所存在的空文件里。记住,使用DEFINE命令中的MODEL参数极容易建立一个以另一个文件为基础的文件,这个基础文件里所有的属性几乎都能满足目标文件的需要,然后指定一些附加的属性以完善DEFINE命令。

3.2.9 维护可移植备份的次索引

至今为止,还未讨论更改索引,但在使用EXPORT和IMPORT时确实暗示它们将影响索引。EXPORT和IMPORT命令可以用像备份和恢复VSAM文件那样,备份和恢复次索引。当使用PERMANENT选项建立一个替换索引的可移植备份时,所有与替换索引有关的路径都将被删除;当带有次索引和路径(PATH)的VSAM文件使用PERMANENT选项建立可移植备份时,所有替换的索引和路径都会被自动删除。这意味着,与基本文件(BASE CLUSTER)有关的替换索引应在基本文件的可移植备份建立之前产生。当恢复(IMPORT)输入这些目标时,首先恢复基本文件,接下来才是替换索引。按照此顺序进行备份和恢复能确保文件的所有目录、替换索引、路径都能正确地得以备份和恢复。

3.2.10 备份和恢复目录

REPRO命令用来复制用户目录里的内容,同时建立一个备份副本用于以后恢复使用。当用REPRO从用户目录的备份副本中恢复时,输出目录必须为空。

从备份中恢复用户目录不是简单的操作,有许多信息必须满足VSAM目录的需要,才能确保正确的运作,只要出现一个很小的错误,整个结构都不能使用。

下面的作业流将在磁带上建立一个用户目录UCDMTP08的备份。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS   EXEC PGM=IDCAMS,REGION=4096K
        000004 //STEPCAT  DD  DSN=UCDMTP08,DISP=SHR
        000005 //SYSPRINT DD  SYSOUT=A
        000006 //BACKUP   DD  UNIT=TAPE,DISP=(NEW,KEEP),
        000007 //             DSN=BACKUP.UCDMTP08,
        000008 //             DCB=BLKSIZE=31744
        000009 //SYSIN   DD  *
        000010
        000011   REPRO INDATASET(UCDMTP08)                             -
        000012         OUTFILE(BACKUP)
        000013
        000014 /*
        000015 //

下面的作业流将从前一个作业流建立的备份副本中,恢复用户目录UCDMTP08,因为REPRO的目标必须为空,首先需要删除和重定义用户目录。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //DEFUCAT  EXEC PGM=IDCAMS,REGION=4096K
        000004 //SYSPRINT DD  SYSOUT=A
        000005 //SYSIN    DD  *
        000006   DELETE (UCDMTP08)                                    -
        000007          USERCATALOG FORCE PURGE
        000008   IF LASTCC = 0 THEN                                   -
        000009         DEFINE USERCATALOG (                            -
        000010                      NAME (UCDMTP08)                     -
        000011                      VOLUME (DMTP08)                     -
        000012                      TRACKS (15)                        -
        000013                      FOR (9999) )
        000014 /*
        000015 //REPROUC  EXEC PGM=IDCAMS,REGION=4096K,COND=(0,NE)
        000016 //STEPCAT  DD  DSN=UCDMTP08,DISP=SHR
        000017 //SYSPRINT DD  SYSOUT=A
        000018 //BACKUP   DD  UNIT=(TAPE,,DEFER),DISP=(OLD,KEEP),
        000019 //             DSN=BACKUP.UCDMTP08,VOL=SER=TAP001
        000020 //SYSIN   DD  *
        000021   REPRO INFILE(BACKUP)                                 -
        000022         OUTDATASET(UCDMTP08)
        000023 /*
        000024 //

作业流的SYSOUT是IBMUSERA,系统为每一个被恢复的目标发送信息:IDC1575I ONLY BACKUP DEFINES <object name>,因为信息可以用来建立目标的目录入口,目标只能从磁带上获取。

3.2.11 删除VSAM和非VSAM目标

DELETE命令把指定的文件的入口从目录中移走,并且也可以删除目标本身。如果数据集是存放在直接存取存储器上的话,还可以释放由文件占有的空间。DELETE命令的语法格式为:

从命令中可以看出,多种VSAM和非VSAM目标都可以通过DELETE命令删除,DELETE命令删除与指定入口名有关的所有目标。默认情况下,有一定保留期的目标未到期之前不能被删除,但可通过PURGE选项强制删除。指定ERASE/NOERASE选项可以用来覆盖原来目录中的ERASE属性。指定FORCE选项导致删除指定的目标(SPACE、USERCATALOG、GENERATIONDATAGROUP),即使它们不空。指定SCRATCH选项导致与目标有关的入口从VTOC中移出,这经常适用于非VSAM数据集。用于删除用户目录的DELETE命令中可以不指定CATALOG选项,用户目录的入口只能从主目录中删除。

下面的作业流将删除非VSAM数据集、用户目录和用户目录的别名。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS  EXEC PGM=IDCAMS,REGION=4096K
        000004 //SYSPRINT DD  SYSOUT=A
        000005 //SYSIN   DD  *
        000006
        000007   /* DELETE CATALOGUED NON-VSAM DATASET                  */
        000008
        000009   DELETE (IBMUSER.TEST.DATA)                            -
        000010          NONVSAM SCRATCH PURGE
        000011
        000012   /* DELETE ALIAS TO USER CATALOG                       */
        000013
        000014   DELETE (DMTP08)                                     -
        000015          ALIAS
        000016
        000017   /* DELETE USER CATALOG                               */
        000018   DELETE (UCDMTP08)                                    -
        000019          USERCATALOG FORCE PURGE
        000020   /*
        000021   //

作业流的SYSOUT是DELETE1,非VSAM数据集的入口从目录里UNCATLG出来了并从卷DMTP08上的VTOC中移出,因为包含了SCRATCH选项。

3.2.12 显示目录清单

LISTCAT命令显示目录的清单信息。根据前面所述,可以从SYSOUT清单中的LISTCAT命令看到输出。好的习惯是在每次建立了新的目标(文件、索引和目录等)之后,立即显示目标项的清单,以确定你希望建立的目标是否已经建立起来,以及所建立的目标是否具备你所希望的属性。对VSAM目标而言,我们经常需要显示它的一些字段来诊断问题。LISTCAT命令的语法格式是:

        LISTCAT
          [ALIAS] |
          [ALTERNATEINDEX] |
          [CLUSTER] |
          [DATA] |
          [GENERATIONDATAGROUP] |
          [INDEX] |
          [NONVSAM] |
          [PAGESPACE] |
          [PATH] |
          [SPACE] |
          [USERCATALOG]
          [CREATION(days)]
          [ENTRIES(entry name[/password] [ entryname[/password]...])  |
          LEVEL(level)]
          [EXPIRATION(days)]
          [NAME  |  HISTORY  |   VOLUME  |  ALLOCATION  |  ALL]
          [OUTFILE(ddname)]
          [CATALOG(catname[/password])]

LISTCAT命令的所有参数都是可选的。参数的第一组(以ALIAS开始USERCATALOG结束)是位置参数,指定要显示的目录清单类型,可以指定一个或多个这类参数。如果没有指定,只显示清单而忽略类型。

CREATION指定天数,只有在它们的建立日期的指定天数之前,才显示目录信息。

EXPIRATION也指定天数,只有在指定天数到期或更早,才显示目录信息。

参数NAME、HISTORY、VOLUME、ALLOCATION都用来指定要显示的目录清单的信息类型,NAME(默认值)只指定显示的名字和目录类型;HISTORY指定名字、目录类型、所有者、创建日期和到期日;VOLUME指定HISTORY参数显示的所有信息,还显示卷标和设备类型;ALLOCATION指定VOLUME参数显示的所有信息和有关空间分配的详细资料。所有的参数都显示了目录清单的所有信息。

OUTFILE可以用来指定LISTCAT命令的输出,命令应以DD name编写而不是SYSPRINT。

无论是ENTRIES还是LEVEL参数,都可以用来选择目录里要显示的目标清单,一个或多个目标的名字可以包含在ENTRIES参数的子参数中,以选择指定的目标。也可以使用部分文件名去选择以名字的结构为基础的多个目录项。使用带(*)的部分文件名表示要查看的是以该段名字开头的目标的清单。LEVEL提供了另一种指定部分文件名的方法。当在LEVEL参数里指定一个或多个高位限定符时,所有以该限定符开头的目标都会显示出来,不管它们的名字有多长。

下面的作业流说明LISTCAT命令的几个选项。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS  EXEC PGM=IDCAMS,REGION=4096K
        000004 //SYSPRINT DD  SYSOUT=A
        000005 //SYSIN    DD  *
        000006   LISTCAT ENT(IBMUSER.DB2.*) ALL
        000007   LISTCAT LEVEL(IBMUSER.TEST) ALL
        000008 /*
        000009 //

作业流的SYSOUT是IBMUSERA。它显示的是所有以IBMUSER.DB2开头和以IBMUSER.TEST开头的文件、别名和目录等的信息。

3.2.13 打印或显示数据集内容

PRINT命令用来打印VSAM和非VSAM数据集的内容。其命令的语法格式为:

        PRINT {INFILE(ddname[/password])  |
              INDATASET(entryname[/password])}
                  [CHARACTER  |  DUMP  |  HEX]
                  [FROMKEY(key)  |  FROMADDRESS(address)  |
                  FROMNUMBER(number)  |  SKIP(number)]
              [OUTFILE(ddname)]
                  [TOKEY(key)  |  TOADDRESS(address)  |
                  TONUMBER(number)  |  COUNT(number)]

必需的参数只有INFILE或INDATASET,用来指定要显示或打印记录的数据集。当使用INFILE时,记录从JCL设定的DD name中读取,并且这个DD语句必须由与其name相匹配的JCL语句定义。当使用INDATASET时,系统通过搜寻与目标相匹配的VSAM目录来找到指定的输入文件。PRINT命令中无CATALOG选项,所以如果使用INDATASET,并且没有定义目录的别名,那么,你必须在你的JCL中使用JOBCAT或STEPCAT DD语句以指定适当的目录(CATALOG)。

现在对显示或打印VSAM文件内容的参数做以下说明。

● 指定打印记录的起始位置。

✧ FROMKEY指定打印操作起始点记录的键值,FROMKEY只适用于KSDS输入数据集。

✧ FROMADDRESS指定打印操作起始点记录的RBA值,FROMADDRESS只适用于KSDS输入数据集和ESDS数据集。

✧ FROMNUMBER指定打印操作起始点的记录的相对记录号,FROMNUMBER只适用于RRDS输入数据集。

✧ SKIP用来指定在打印操作开始之前需要跳过的输入数据集记录个数。

● 指定打印记录的结束位置。

✧ TOKEY指定打印操作结束记录的全键值或部分键值,TOKEY只适用于KSDS输出文件。

✧ TOADDRESS指定打印操作结束记录的RBA值,TOADDRESS只适用于KSDS或ESDS输出文件。

✧ TONUMBER指定打印操作结束记录的相对记录号,TONUMBER只适用于RRDS输出文件。

✧ COUNT参数可以指定打印到输出文件的记录个数,当指定的记录个数达到时,打印操作就会结束。

● 输出格式。

打印格式可以设定为CHARACTER、DUMP(默认值)或HEX。CHARACTER表示逻辑记录的每一个字节都按字符格式打印,DUMP表示逻辑记录的每一个字节都以十六进制格式或字符格式打印,HEX表示逻辑记录的每一个字节都以两个十六进制数字打印。

下面的作业流说明了PRINT命令同时打印3个数据集:一个非VSAM文件和两个VSAM文件的用法。

        000001 //IBMUSERA JOB 168,'NEWMAN LV',CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),
        000002 // NOTIFY=IBMUSER
        000003 //IDCAMS  EXEC PGM=IDCAMS,REGION=4096K
        000004 //BKTRAN  DD  DSN=IBMUSER.TEST.BKTRAN,DISP=OLD
        000005 //BKTRAN1 DD  DSN=IBMUSER.TEST.BKTRAN.RRDS.CLUSTER,DISP=SHR
        000006 //BKTRAN2 DD  DSN=IBMUSER.TEST.BKTRAN.KSDS.CLUSTER,DISP=SHR
        000007 //*
        000008 //SYSPRINT DD  SYSOUT=A
        000009 //SYSIN   DD  *
        000010   /* PRINT NON-VSAM DATASET                             */
        000011   PRINT INFILE(BKTRAN)                   -
        000012         CHAR COUNT(10)
        000013
        000014   /* PRINT RRDS DATASET                                */
        000015   PRINT INFILE(BKTRAN1)                  -
        000016         HEX SKIP(90) COUNT(15)
        000017
        000018   /* PRINT KSDS DATASET                                */
        000019   PRINT INFILE(BKTRAN2)                  -
        000020         FROMKEY(0006) TOKEY(0010)          -
        000021          DUMP
        000022
        000023 /*
        000024 //

作业流的SYSOUT是PRINT1。第11行到第12行的打印语句打印非VSAM文件,从第1条记录开始,供打印10条记录,输出格式为字符串。第15行到第16行的打印语句打印RRDS文件,从第91条记录开始(跳过前面的90条记录),共定义15条,打印输出格式是十六进制格式,即1个字符由2个字节组成,比如数字1显示为F1,字母A显示为C1等,具体的你要知道EBCDIC码的编码规则。第19行到第21行的PRINT命令列印从关键字为0006到关键字为0010的记录,打印格式为DUMP格式,即跟HEX格式一样,不过在每4个字节之间多留了一个空格而已。

3.2.14 修改文件属性

你可以使用ALTER命令修改文件的大多数属性,这些属性是在定义VSAM文件期间设定的。ALTER命令的语法格式为:

        ALTER entryname[/password]
          [ADDVOLUMES(volser[ volser...])]
          [BUFFERSPACE(size)]
          [EMPTY  |  NOEMPTY]
          [ERASE  |  NOERASE]
          [FREESPACE(CI-percent[ CA-percent])]
          [KEYS(length offset)]
          [NEWNAME(newname)]
          [RECORDSIZE(average maximum)]
          [REMOVEVOLUMES(volser[ volser...])]
          [SCRATCH  |  NOSCRATCH]
          [TO(date)  |  FOR(days)]
          [UPGRADE  |  NOUPGRADE]

          [CATALOG(catname[/password])]

注意这个简化的语法图中并未包含某些高级的可选参数,因为大多数参数都对应于DEFINE命令里使用的参数,所以在此就不重复说明有关的细节了。

3.2.15 辅助索引

VSAM除了建立主索引外还可以建立一个或多个辅助索引。对于KSDS而言,我们可以根据文件的记录内容建立主键以外的次索引,使得我们可以按照多种顺序存取文件。对于没有索引的文件类型,比如ESDS文件,我们也可以为其建立次索引,使得我们除了顺序存取ESDS外还可以按照次索引的顺序存取它。

建立辅助索引的3个步骤为:

● 使用DEFINE命令建立辅助索引。

● 使用BLDINDEX命令建立辅助索引的键。

● 使用DEFINE命令建立路径(PATH),将辅助索引与基本文件关联起来。

辅助索引文件是键顺序文件(KSDS)用来保存次索引关键字及其指向基本文件相关记录的指针。

DEFINE ALTERNATEINDEX命令用来定义次索引,其语法格式为:

        DEFINE ALTERNATEINDEX
          (NAME(entryname)
            RELATE(entryname[/password])
            {CYLINDERS(primary[secondary]) |  RECORDS(primary[secondary]) |
              TRACKS(primary[ secondary])}
              VOLUMES(volser[ volser...])
            [BUFFERSPACE(size)]
            [CONTROLINTERVALSIZE(size)]
            [ERASE  |  NOERASE]
            [FILE(ddname)]
            [FREESPACE(CI-percent[ CA-percent]|0 0)
            [IMBED  |  NOIMBED]
            [KEYS(length offset|64 0)]
            [MODEL(entryname[/password][ catname[/password
            [RECORDSIZE(average maximum|408632600)]
            [REPLICATE  |  NOREPLICATE]
            [REUSE  |  NOREUSE]
            [SPEED  |  RECOVERY]
            [TO(date)  |  FOR(days)]
            [UNIQUE  |  SUBALLOCATION]
            [UNIQUEKEY  |  NONUNIQUEKEY]
            [UPGRADE  |  NOUPGRADE])
        [DATA     ([NAME(entryname)])
        [INDEX   ([NAME(entryname)])

       [CATALOG(catname[/password])]

注意,这个简化了的语法图中不包含某些高级的可选参数。对键顺序文件的DEFINE命令而言,大部分的项目是一样的。

下面对一些原来在DEFINE CLUSTER中没有的参数做以下说明。

● RELATE。

命名辅助索引所要定义的基本VSAM文件。基本文件可以是KSDS或者是ESDS,但基本VSAM文件不可以带有REUSE属性,不可以是一个用户目录,也不可以是另一个辅助索引。

● UNIQUEKEY。

表示每一个辅助索引键都是唯一的,即每个辅助索引键在基本VSAM文件里只有一个记录。NONUNIQUEKEY(默认值)表示每个辅助索引键可能对应于基本文件里的多个记录,即辅助索引键在基本文件里是可以重复的。

● UPGRADE。

表示当基本VSAM文件里的记录修改时,辅助索引将自动保持与其一致。NOUPGRADE表示辅助索引不与基本文件保持一致。当指定UPGRAD时,系统会有一个额外的开销,即会对系统的性能有点影响。但在实际应用中,基本上都会保持辅助索引与基本数据集的一致。

● RECORDSIZE。

并不代表基本文件里记录的大小,而是一个经验估算值。估算是以基本文件的主键的长度、辅助索引键值的长度和辅助索引键是UNIQUE还是NONUNIQUE计算出来的。

✧ 如果辅键是UNIQUE,即唯一的。

辅助索引的记录是定长的,长度由下列公式计算出:

对KSDS来说,记录长度=5个字节的控制信息+辅助索引键的长度+主键长度(KSDS)。

对ESDS来说,记录长度=5个字节的控制信息+辅助索引键的长度+RBA长度(对ESDS,即4个字节)。

对定长的KSDS而言,我们可以将上面计算出来的值指定到RECORDSIZE参数里的平均值和最大值中。

✧ 如果辅键是NONUNIQUE,即可以重复。

辅助索引文件的记录长度就是变长的,平均长度的计算由下列几项构成:

对KSDS而言,平均长度=5个字节的控制信息+辅助索引键的长度+主键长度乘以重复键的平均数。

对ESDS而言,平均长度=5个字节的控制信息+辅助索引键的长度+4乘以重复键的平均数,其中4是RBA的长度。

最大长度的计算方法为:

对KSDS而言,平均长度=5个字节的控制信息+辅助索引键的长度+主键长度乘以重复键的最大数。

对ESDS而言,平均长度=5个字节的控制信息+辅助索引键的长度+4乘以重复键的最大数,其中4是RBA的长度。

控制信息的5个字节内容存储在辅助索引记录里,表示基本文件的类型,辅助索引点和键的长度,即:

✧ 第1个字节表示基本文件类型,x'01' 代表KSDS,x'00'代表ESDS。

✧ 第2个字节表示存储在辅助索引记录里基本文件指针的长度,如果基本文件是KSDS x'主键长度,或者如果文件是ESDS x'04'表示。

✧ 第3 和第4 个字节是半字节值表示在辅助索引记录里基本文件指针发生的数目,例如,含有x'0001'是对UNIQUE辅助键的。

✧ 第5个字节表示辅助索引间的长度。

下面的作业流在我们前面定义的基本数据集IBMUSER.TEST.BKTRAN.KSDS.CLUSTER上建立一个辅助索引。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //TRANAIX  EXEC  PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=A
        000005 //SYSIN    DD   *
        000006   DELETE IBMUSER.TEST.BKTRAN.KSDS.AIX
        000007   SET MAXCC=0
        000008   DEFINE ALTERNATEINDEX -
        000009          (NAME(IBMUSER.TEST.BKTRAN.KSDS.AIX) -
        000010          RELATE(IBMUSER.TEST.BKTRAN.KSDS.CLUSTER) -
        000011          VOLUMES(ES0D94) -
        000012          KEYS(14 07) -
        000013          RECORDSIZE(10241024) -
        000014          TRACKS(5 5) -
        000015          NONUNIQUEKEY -
        000016          UPGRADE) -
        000017          DATA(NAME(IBMUSER.TEST.BKTRAN.KSDS.AIX.DATA)) -
        000018          INDEX(NAME(IBMUSER.TEST.BKTRAN.KSDS.AIX.IDX))
        000019 /*
        000020 //

第10行的RELATE语句将现在定义的次索引与基本数据集IBMUSER.TEST.BKTRAN.KSDS. CLUSTER联系起来,表明该次索引是建立在其上的。第12行的KEY参数定义了次索引的关键字的长度为14,关键字的起始位置为7,结合我们的记录格式就可以知道,次索引是以账号为关键字的。

第13行的RECORDSIZE定义了次索引文件的记录长度,由于第15行的NONUNIQUEKEY参数,我们知道该关键字是可以重复的,这样记录长度就是一个估计值,通常我们都将次索引的记录长度定义成1024的倍数。第16行的UPGRADE参数表明次索引会与基本数据集保持同步,即当基本数据集中有记录增加或删除时,次索引也会跟着更新,虽然这样可能会增加某些开销,但在联机交易中,保持数据的准确性显得就更重要了。

建立索引的含义是系统根据基本数据集中数据的内容和次索引定义的键值等属性,将次索引建立起来。我们知道,次索引本身也是一个VSAM的KSDS文件,它也包含DATA和INDEX部分。

建立索引BLDINDEX的语法格式为:

        BLDINDEX
        {INFILE(ddname[/password])  |   INDATASET(entryname[/password])}
        {OUTFILE(ddname[/password] [ ddname[/password]...])  |
        OUTDATASET(entryname[/password] [ entryname[/password]...])}
        [WORKFILES(ddname ddname)]

        [CATALOG(catname[/password])]

此简化的语法图中不包含某些高级的选项参数。AMS顺序地读取基本文件,并从基本文件里的每一个记录中生成辅键/指针对。如果基本文件是KSDS,每一个指针由主键值构成;如果基本文件是ESDS, 每一个指针由RBA指针构成。

AMS对辅键/指针对排序并按照辅键的升序顺序装载记录。对一个大的基本文件而言,分类可以通过工作文件完成,工作文件在JCL中需要定义相关的DD语句。

被分类的辅键/指针对用来装载记录到辅助索引文件数据部分中,把控制信息加入到每一个辅键/指针对中,告知VSAM辅键长度,描述哪一个指针是主键的RBA,指出哪个键是UNIQUE或NONUNIQUE,并指出每一个主键指针的长度。

可以使用INFILE或INDATASET指定基本文件。INFILE由JCL中的DD语句定义对应的基本文件,INDATASET命名基本文件并通过VSAM目录定位。

同样,OUTFILE或OUTDATASET指定目标辅助索引文件。可以装载多个辅助索引,通过对同一个基本文件执行单个BLDINDEX命令,可以装载多个辅助索引,所以OUTFILE可以指定多个DD names,同样地,OUTDATASET也可以指定多个辅助索引项的名字。

作为默认值,系统执行一个内部分类按升序排列辅键。如果没有足够的虚拟存储空间去执行分类,将自动执行一个外部分类,如果需要一个外部分类,必须提供两个工作文件。这些文件的默认DD names是IDCUT1和IDCUT2,这些DD names可以由WORKFILES参数覆盖。

下面的作业流使用BLDINDEX命令去建立辅键和装载辅助索引。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //BDTRIDX  EXEC  PGM=IDCAMS
        000004 //BASEDD   DD   DSNAME=IBMUSER.TEST.BKTRAN.KSDS.CLUSTER,DISP=OLD
        000005 //AIXDD    DD   DSNAME=IBMUSER.TEST.BKTRAN.KSDS.AIX,DISP=OLD
        000006 //SYSPRINT DD   SYSOUT=A
        000007 //SYSIN    DD   *
        000008   BLDINDEX INFILE(BASEDD) -
        000009             OUTFILE(AIXDD)
        000010 /*

到目前为此,有两个键顺序文件,一个是基本文件本身,另外一个是次索引文件,它们包含的数据是逻辑相关的。为了便于使用物理文件,必须将次索引与基本文件关联起来,因此需要建立一个PATH。

定义路径DEFINE PATH命令的语法结构为:

        DEFINE PATH
          (NAME(entryname)
            PATHENTRY(entryname[/password])
            [FILE(ddname)]
            [MODEL(entryname[/password] [ catname[/password]])]
            [TO(date)  |  FOR(days)]
            [CATALOG(catname[/password])]

注意,我们将某些高级的选项参数从简化的语法图中去掉了。在上面的语法结构中,NAME指定PATH的名字,PATHENTRY指定PATH所指向的辅助索引文件名。当PATH建立起来后,按照PATH存取VSAM文件时,系统将会按照辅助索引键值的顺序将基本文件的记录返回给程序。

下面的作业流介绍用DEFINE PATH命令去建立辅助索引的PATH。

        000001 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1),NOTIFY=&SYSUID,
        000002 //     REGION=4M
        000003 //TRANAIX  EXEC  PGM=IDCAMS
        000004 //SYSPRINT DD   SYSOUT=A
        000005 //SYSIN    DD   *
        000006   DEFINE PATH -
        000007          (NAME(IBMUSER.TEST.BKTRAN.KSDS.PATH) -
        000008          PATHENTRY(IBMUSER.TEST.BKTRAN.KSDS.AIX))
        000009
        000010   /* PRINT PATH DATASET                      */
        000011   LISTC ENT(IBMUSER.TEST.BKTRAN.KSDS.PATH) ALL
        000012   PRINT INFILE(PATH)                         -
        000013         CHAR
        000014 /*
        000015 //

从下面的LISTCAT输出里的ASSOCIATIONS部分,我们可以看到,PATH与辅助索引文件和基本记录文件里的所有部分都有关联。

          LISTC ENT(IBMUSER.TEST.BKTRAN.KSDS.PATH) ALL
        0PATH ---------- IBMUSER.TEST.BKTRAN.KSDS.PATH
            IN-CAT --- CATALOG.MASTER.MCAT
            HISTORY
              DATASET-OWNER-----(NULL)    CREATION--------2010.237
              RELEASE----------------2    EXPIRATION------0000.000
            PROTECTION-PSWD-----(NULL)    RACF----------------(NO)
            ASSOCIATIONS
              AIX------IBMUSER.TEST.BKTRAN.KSDS.AIX
              DATA-----IBMUSER.TEST.BKTRAN.KSDS.AIX.DATA
              INDEX----IBMUSER.TEST.BKTRAN.KSDS.AIX.IDX
              DATA-----IBMUSER.TEST.BKTRAN.DATA
              INDEX----IBMUSER.TEST.BKTRAN.INDEX
            ATTRIBUTES
              UPDATE
      0        THE NUMBER OF ENTRIES PROCESSED WAS:
                        AIX -------------------0
                        ALIAS -----------------0
                        CLUSTER ---------------0
                        DATA ------------------0
                        GDG -------------------0
                        INDEX -----------------0
                        NONVSAM ---------------0
                        PAGESPACE -------------0
                        PATH ------------------1
                        SPACE -----------------0
                        USERCATALOG -----------0
                        TAPELIBRARY -----------0
                        TAPEVOLUME ------------0
                        TOTAL -----------------1

3.2.16 核实VSAM数据集

如果作业异常终止,没有关闭VSAM数据集,系统就会标记数据集可能已经破坏。在数据集重新打开之前,必须使用VERIFY命令正确地标记数据集的尾部,并重新正确地设置目录项。

VERIFY命令的语法格式为:

        VERIFY {FILE(ddname[/password])  |
            DATASET(entryname[/password])}

要核实的数据集可以通过FILE命令指定,必须在JCL中用相应的DD语句定义该数据集。你也可以通过DATASET命令指定要核实的数据集,这时它必须存在于你指定的目录里。VERIFY命令没有CATALOG选项,除非目标文件的入口是在主目录里,或目标名的第1个限定符包含目标的用户目录的别名,否则在你的JCL语句中,必须包含JOBCAT或STEPCAT DD语句。

下面的作业流核实VSAM数据集IBMUSER.TEST.BKTRAN.RRDS.CLUSTER。

        000001 //IBMUSERA  JOB ACCT#,IBMUSER,NOTIFY=IBMUSER,MSGLEVEL=(1,1)
        000002 //VERIFY   EXEC PGM=IDCAMS
        000003 //SYSPRINT DD   SYSOUT=*
        000004 //IN1     DD   DSN=IBMUSER.TEST.BKTRAN.RRDS.CLUSTER,DISP=SHR
        000005 //SYSIN   DD   *
        000006   VERIFY FILE(IN1)
        000007 /*
        000008 //