ESDS にアクセスするのに使用する SEQUENTIAL ファイルは、INPUT 属性または UPDATE 属性を使用して オープンすることができます。KEY オプションまたは KEYTO オプションを使用する場合には、ファイルには、KEYED 属性も必要です。
順次アクセスの順序は、レコードをデータ・セットに初めにロードしたときと同じです。 読み取られるレコードの RBA を回復するには、READ ステートメント で KEYTO オプションを使用します。KEY オプションを使用すると、回復されるレコードは、ユーザーが指定する RBA を持つレコードになります。 次の順次アクセスは、データ・セットの新しい場所から開始されます。
UPDATE ファイルの場合、WRITE ステートメントは、データ・セットの終わりに新 たにレコードを付け加えます。REWRITE ステートメントでは、 再書き込みの行われるレコードは、KEY オプションを 使用する場合は、指定された RBA を持つものであり、 そうでない場合には、直前の READ で アクセスされたレコードです。REWRITE ステートメントで置き換えようとするレコードの長さを 変更してはなりません。
入力順データ・セットでは、DELETE ステートメントは使用できません。
図 35 では、データ・セットは DEFINE CLUSTER コマンドで 定義され、PLIVSAM.AJC1.BASE という名前が与えられています。NONINDEXED キーワードを使用すると、ESDS が定義されることになります。
PL/I プログラムは、SEQUENTIAL OUTPUT ファイルと WRITE FROM ステート メントを使ってデータ・セットを書き込みます。 このファイル用の DD ステートメントには、DEFINE CLUSTER コマンドの NAME パラメーター で与えられたデータ・セットの DSNAME が入っています。
レコードの RBA は、KEYED ファイル内のキーとして後で使用するために、 書き込み時に入手しておくこともできます。 それを行うには、キーを保持する適切な変数と、 使用する WRITE...KEYTO ステートメントを宣言しておく必要があります。 次に例を示します。
DCL CHARS CHAR(4); WRITE FILE(FAMFILE) FROM (STRING) KEYTO(CHARS);
通常、キーは印刷できませんが、 後で使用するときのためにとっておくことができることに注意してください。
カタログ式プロシージャー IBMZCBG を使用しています。 同じプログラム (図 35 参照) を使ってデータ・セットにレコードを 追加できるため、このプログラムはライブラリーに保持されています。 このプロシージャーの例を次に示します。
//OPT9#7 JOB
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DEFINE CLUSTER -
(NAME(PLIVSAM.AJC1.BASE) -
VOLUMES(nnnnnn) -
NONINDEXED -
RECORDSIZE(80 80) -
TRACKS(2 2))
/*
//STEP2 EXEC IBMZCLG
//PLI.SYSIN DD *
CREATE: PROC OPTIONS(MAIN);
DCL
FAMFILE FILE SEQUENTIAL OUTPUT ENV(VSAM),
IN FILE RECORD INPUT,
STRING CHAR(80),
EOF BIT(1) INIT('0'B);
ON ENDFILE(IN) EOF='1'B;
READ FILE(IN) INTO (STRING);
DO I=1 BY 1 WHILE (¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT (STRING) (A);
WRITE FILE(FAMFILE) FROM (STRING);
READ FILE(IN) INTO (STRING);
END;
PUT SKIP EDIT(I-1,' RECORDS PROCESSED')(A);
END;
/*
//LKED.SYSLMOD DD DSN=HPU8.MYDS(PGMA),DISP=(NEW,CATLG),
// UNIT=SYSDA,SPACE=(CYL,(1,1,1))
//GO.FAMFILE DD DSNAME=PLIVSAM.AJC1.BASE,DISP=OLD
//GO.IN DD *
FRED 69 M
ANDY 70 M
SUZAN 72 F
/*図 36 は、ESDS の終わりに新しいレコードを追加する例を示しています。 これは、図 35 に示したプログラムを再度実行して行います。SEQUENTIAL OUTPUT ファイルが使用され、図 35 に示した DEFINE コマンドに指定された名前 PLIVSAM.AJC1.BASE を指定する DSNAME パラメーターを使用して、 データ・セットをこのファイルと関連付けています。
//OPT9#8 JOB //STEP1 EXEC PGM=PGMA //STEPLIB DD DSN=HPU8.MYDS(PGMA),DISP=(OLD,KEEP) // DD DSN=CEE.SCEERUN,DISP=SHR //SYSPRINT DD SYSOUT=A //FAMFILE DD DSN=PLIVSAM.AJC1.BASE,DISP=SHR //IN DD * JANE 75 F //
レコードの長さを変えないかぎり、ESDS 内の既存レコードを再書き込みすることができます。 これには、SEQUENTIAL または KEYED SEQUENTIAL 更新ファイルを使用します。 キーを使用する場合は、RBA または 代替索引 パスのキーを使用することができます。
ESDS では削除を行うことはできません。
索引付き VSAM データ・セットで使用できるステートメントとオプションは、表 28 に示してあります。 索引付きデータ・セットは基本索引を持つ KSDS、 または代替索引 を持つ KSDS または ESDS にすることができます。 特に断り書きがなければ、次の説明はすべての索引付き VSAM データ・セットに適用されます。
|
有効ステートメント および必須オプション |
指定できるその他の オプション |
|
|---|---|---|
|
SEQUENTIAL OUTPUT BUFFERED |
WRITE FILE(file-reference) FROM(reference) KEYFROM(expression); LOCATE 基底付き変数 FILE(file-reference) KEYFROM(expression); |
SET(pointer-reference) |
|
SEQUENTIAL INPUT BUFFERED |
READ FILE(file-reference) INTO(reference); READ FILE(file-reference) SET(pointer-reference); READ FILE(file-reference);2 |
KEY(expression) または KEYTO(reference) KEY(expression) または KEYTO(reference) IGNORE(expression) |
|
SEQUENTIAL UPDATE BUFFERED |
READ FILE(file-reference) INTO(reference); READ FILE(file-reference) SET(pointer-reference); READ FILE(file-reference);2 WRITE FILE(file-reference) FROM(reference) KEYFROM(expression); REWRITE FILE(file-reference); DELETE FILE(file-reference) |
KEY(expression) または KEYTO(reference) KEY(expression) または KEYTO(reference) IGNORE(expression) FROM(reference) および/またはKEY(expression) KEY(expression) |
|
DIRECT BUFFERED |
READ FILE(file-reference) INTO(reference) KEY(expression); READ FILE(file-reference) SET(pointer-reference) KEY(expression); |
|
|
DIRECT OUTPUT BUFFERED |
WRITE FILE(file-reference) FROM(reference) KEYFROM(expression); |
|
|
DIRECT BUFFERED |
READ FILE(file-reference) INTO(reference) KEY(expression); READ FILE(file-reference) SET(pointer-reference) KEY(expression); REWRITE FILE(file-reference) FROM(reference) KEY(expression); DELETE FILE(file-reference) KEY(expression); WRITE FILE(file-reference) FROM(reference) KEYFROM(expression); |
|
|
注:
|
||
KSDS をロードするときには、KEYED SEQUENTIAL OUTPUT 用の 関連ファイルをオープンする必要があります。 レコードは昇順のキー順で提示しなければならず、KEYFROM オプションを使用しなければなりません。 データ・セットをロードするためには基本索引を使用しなければならないことに注意してください。 代替索引 を介して VSAM データ・セットをロードすることはできません。
KSDS に既にレコードがあって、SEQUENTIAL 属性と OUTPUT 属性を持つ関連ファイル をオープンする場合は、データ・セットの終わりにしかレコードを追加することはできません。 前項のルールが適用されます。 特に、指定する最初のレコードはデータ・セット上に存在する 最高位のキーより大きいキーを持っていなくてはなりません。
図 37 は、KSDS を定義するのに使用する DEFINE コマンドを示しています。 データ・セットには PLIVSAM.AJC2.BASE という名前が与えられ、INDEXED オペランド が使用されているため、KSDS と定義されています。 レコード内のキーの位置は、KEYS オペランド内で定義されます。
PL/I プログラムでは、WRITE...FROM...KEYFROM ステートメント で KEYED SEQUENTIAL OUTPUT ファイルが使用されます。 データは、昇順のキー順で提示されます。KSDS はこの方法でロードしなければなりません。
ファイルは、DEFINE コマンドで付けられた名前を DSNAME パラメーター として使用する DD ステートメントによってデータ・セットに関連付けられます。
//OPT9#12 JOB
// EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DEFINE CLUSTER -
(NAME(PLIVSAM.AJC2.BASE) -
VOLUMES(nnnnnn) -
INDEXED -
TRACKS(3 1) -
KEYS(20 0) -
RECORDSIZE(23 80))
/*
// EXEC IBMZCBG
//PLI.SYSIN DD *
TELNOS: PROC OPTIONS(MAIN);
DCL DIREC FILE RECORD SEQUENTIAL OUTPUT KEYED ENV(VSAM),
CARD CHAR(80),
NAME CHAR(20) DEF CARD POS(1),
NUMBER CHAR(3) DEF CARD POS(21),
OUTREC CHAR(23) DEF CARD POS(1),
EOF BIT(1) INIT('0'B);
ON ENDFILE(SYSIN) EOF='1'B;
OPEN FILE(DIREC) OUTPUT;
GET FILE(SYSIN) EDIT(CARD)(A(80));
DO WHILE (¬EOF);
WRITE FILE(DIREC) FROM(OUTREC) KEYFROM(NAME);
GET FILE(SYSIN) EDIT(CARD)(A(80));
END;
CLOSE FILE(DIREC);
END TELNOS;
/*
//GO.DIREC DD DSNAME=PLIVSAM.AJC2.BASE,DISP=OLD
//GO.SYSIN DD *
ACTION,G. 162
BAKER,R. 152
BRAMLEY,O.H. 248
CHEESEMAN,D. 141
CORY,G. 336
ELLIOTT,D. 875
FIGGINS,S. 413
HARVEY,C.D.W. 205
HASTINGS,G.M. 391
KENDALL,J.G. 294
LANCASTER,W.R. 624
MILES,R. 233
NEWMAN,M.W. 450
PITT,W.H. 515
ROLF,D.E. 114
SHEERS,C.D. 241
SUTCLIFFE,M. 472
TAYLOR,G.C. 407
WILTON,L.W. 404
WINSTONE,E.M. 307
//KSDS にアクセスするのに使用する SEQUENTIAL ファイルは、INPUT 属性または UPDATE 属性 を使用してオープンすることができます。
KEY オプションを指定しない READ ステートメントの場合、 レコードは昇順のキー順 (ただし、BKWD オプションを使用すると、降順のキー順) で回復されます。 このように、KEY オプションによって、回復されたレコードのキーを得ることができます。
KEY オプションを使用すると、READ ステートメントで回復されるレコードは、 指定したキーを持つレコードになります。 このような READ ステートメントはデータ・セットを指定されたレコードに 位置付け、その後の順次読み取りは後続のレコードを順番に回復します。
KEYFROM オプションのある WRITE ステートメントを、 KEYED SEQUENTIAL UPDATE ファイルで使用することができます。 前回行ったアクセスの位置に関係なく、データ・セット内の任意の位置に 挿入を行うことができます。 固有索引によってデータ・セットにアクセスするときは、 そのデータ・セットに既にあるレコードと同じキーを 持つレコードを挿入しようとすると、KEY 条件が生じます。 非固有索引の場合には、同一キーを持つレコードを後になって検索すると、 レコードがデータ・セットに追加された順に、検索が行われます。
UPDATE ファイルでは、REWRITE ステートメントは、KEY オプションのあるなしに 関係なく使用できます。KEY オプションを使用した場合、 再書き込みされるレコードは、指定されたキーを持つ 最初のレコードであり、それ以外の場合は直前の READ ステートメントによってアクセスされた レコードです。 代替索引 を使用してレコードを再書き込みする場合は、 レコードの基本キーを変更しないでください。
索引付き VSAM データ・セットにアクセスするのに 使用する DIRECT ファイルをオープンするには、INPUT 属性、OUTPUT 属性 または UPDATE 属性を指定します。 DIRECT ファイルを、非固有索引によってデータ・セットにアクセスするのに使用しないでください。
DIRECT OUTPUT ファイルを使ってデータ・セットに レコードを追加するときに、そのデータ・セット に既にあるレコードと同じキーを持つレコードを挿入しようとすると、KEY 条件が生じます。
DIRECT INPUT ファイルまたは DIRECT UPDATE ファイルを 使用すれば、KEYED SEQUENTIAL ファイルの場合と同様に、 レコードの読み取り、書き込み、再書き込み、または削除が行えます。
図 38 は、基本索引を使って KSDS を更新する 1 つの方法を示しています。
//OPT9#13 JOB
//STEP1 EXEC IBMZCBG
//PLI.SYSIN DD *
DIRUPDT: PROC OPTIONS(MAIN);
DCL DIREC FILE RECORD KEYED ENV(VSAM),
ONCODE BUILTIN,
OUTREC CHAR(23),
NUMBER CHAR(3) DEF OUTREC POS(21),
NAME CHAR(20) DEF OUTREC,
CODE CHAR(1),
EOF BIT(1) INIT('0'B);
ON ENDFILE(SYSIN) EOF='1'B;
ON KEY(DIREC) BEGIN;
IF ONCODE=51 THEN PUT FILE(SYSPRINT) SKIP EDIT
('NOT FOUND: ',NAME)(A(15),A);
IF ONCODE=52 THEN PUT FILE(SYSPRINT) SKIP EDIT
('DUPLICATE: ',NAME)(A(15),A);
END;
OPEN FILE(DIREC) DIRECT UPDATE;
GET FILE(SYSIN) EDIT (NAME,NUMBER,CODE)
(COLUMN(1),A(20),A(3),A(1));
DO WHILE (¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT (' ',NAME,'#',NUMBER,' ',CODE)
(A(1),A(20),A(1),A(3),A(1),A(1));
SELECT (CODE);
WHEN('A') WRITE FILE(DIREC) FROM(OUTREC) KEYFROM(NAME);
WHEN('C') REWRITE FILE(DIREC) FROM(OUTREC) KEY(NAME);
WHEN('D') DELETE FILE(DIREC) KEY(NAME);
OTHERWISE PUT FILE(SYSPRINT) SKIP EDIT
('INVALID CODE: ',NAME) (A(15),A);
END;
GET FILE(SYSIN) EDIT (NAME,NUMBER,CODE)
(COLUMN(1),A(20),A(3),A(1));
END;
CLOSE FILE(DIREC);
PUT FILE(SYSPRINT) PAGE;
OPEN FILE(DIREC) SEQUENTIAL INPUT;
EOF='0'B;
ON ENDFILE(DIREC) EOF='1'B;
READ FILE(DIREC) INTO(OUTREC);
DO WHILE(¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT(OUTREC)(A);
READ FILE(DIREC) INTO(OUTREC);
END;
CLOSE FILE(DIREC);
END DIRUPDT;
/* //GO.DIREC DD DSNAME=PLIVSAM.AJC2.BASE,DISP=OLD //GO.SYSIN DD * NEWMAN,M.W. 516C GOODFELLOW,D.T. 889A MILES,R. D HARVEY,C.D.W. 209A BARTLETT,S.G. 183A CORY,G. D READ,K.M. 001A PITT,W.H. ROLF,D.F. D ELLIOTT,D. 291C HASTINGS,G.M. D BRAMLEY,O.H. 439C /*
DIRECT 更新ファイルが使用され、ファイル SYSIN 内の レコードに渡されたコードにしたがって、データが変更されます。
ラベル NEXT で、名前、番号、およびコードが読み取られ、そのコードの値に従って処理されます。KEY ON ユニットを使用して、誤ったキーに対する処理がとられます。 更新が (ラベル PRINT で) 終了すると、ファイル DIREC はクローズされてから、 属性 SEQUENTIAL INPUT でもう一度オープンされます。 次に、このファイルは順次読み取られ、印刷されます。
このファイルは、図 37 のアクセス方式サービスの DEFINE CLUSTER コマンドで 定義された DSNAME の PLIVSAM.AJC2.BASE を使用する DD ステートメントによって、 データ・セットと関連付けられます。
KSDS を更新する方法は、いくつかあります。 ここに示す DIRECT ファイルを使う方法が、例に示したデータに適しています。 大量順次挿入の場合は、KEYED SEQUENTIAL UPDATE ファイルを使用します。 この方法によると、より高速のパフォーマンスが得られます。 その理由は、データは各 WRITE ステートメントの後ではなく、 本当に必要なときにしかデータ・セットに書き込まれず、 データ・セット内のフリー・スペースの平衡が保たれるからです。
効率的な大量順次挿入を行うためのステートメントは、次のとおりです。
DCL DIREC KEYED SEQUENTIAL UPDATE
ENV(VSAM);
WRITE FILE(DIREC) FROM(OUTREC)
KEYFROM(NAME);
PL/I 入出力ルーチンは、キーが順々になっていることを 検出すると、VSAM に正しい要求を出します。 キーが順々になっていない場合には、そのことが検出され、パフォーマンスの利点は失われますがエラーにはなりません。
代替索引を使用すると、固有キーまたは非固有キーを使用して、 さまざまな方法で KSDS または索引付き ESDS にアクセスできます。
図 39 では、図 35 に定義されロードされた ESDS の固有キー代替索引パスを作成する方法を説明しています。 このパスを使用すると、レコードの最初の 15 バイトの子の名前によって、データ・セットへの索引 付けが行われます。
使用されるアクセス方式サービス・コマンドは、次のとおりです。
代替索引をデータ・セットとして VSAM に定義します。
関連レコードへのポインターを代替索引に入れます。
PL/I ファイルと関連付けるエンティティーを、DD ステートメントで定義します。
DD ステートメントは、BLDINDEX の INFILE および OUTFILE オペランド、ならびに ソート・ファイルで必要です。さまざまな個所で 正しい名前を指定するように注意してください。
//OPT9#9 JOB
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DEFINE ALTERNATEINDEX -
(NAME(PLIVSAM.AJC1.ALPHIND) -
VOLUMES(nnnnnn) -
TRACKS(4 1) -
KEYS(15 0) -
RECORDSIZE(20 40) -
UNIQUEKEY -
RELATE(PLIVSAM.AJC1.BASE))
/*
//STEP2 EXEC PGM=IDCAMS,REGION=512K
//DD1 DD DSNAME=PLIVSAM.AJC1.BASE,DISP=SHR
//DD2 DD DSNAME=PLIVSAM.AJC1.ALPHIND,DISP=SHR
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
BLDINDEX INFILE(DD1) OUTFILE(DD2)
DEFINE PATH -
(NAME(PLIVSAM.AJC1.ALPHPATH) -
PATHENTRY(PLIVSAM.AJC1.ALPHIND))
//図 40 では、ESDS の非固有キー代替索引パスを作成する方法を説明しています。 代替索引を使用すると、子の性によってデータを選択できます。 これにより少女または少年のデータに別々にアクセスでき、 キーを使用して、それぞれのグループの各メンバーにアクセスできます。
使用されるアクセス方式サービス・コマンドは以下の 3 つです。
代替索引をデータ・セットとして VSAM に定義します。
関連レコードへのポインターを代替索引に入れます。
PL/I ファイルと関連付けるエンティティーを、DD ステートメントで定義します。
DD ステートメントは、BLDINDEX の INFILE および OUTFILE オペランド、ならびに ソート・ファイルで必要です。さまざまな個所で 正しい名前を指定するように注意してください。
NONUNIQUEKEY オペランドを使用すると、索引が非固有キーを持つように指定できます。 非固有キーを持つ索引を作成する場合は、 指定する RECORDSIZE が十分大きくなるように注意してください。 非固有代替索引では、それぞれの代替索引レコードが、関連した索引キーを持つすべての レコードへのポインターを含みます。ポインターは、ESDS の場合は RBA の形式で、KSDS の場合は基本キーの形式です。多くのレコードが同じキーを持つ場合は、 大きなレコードが必要です。
//OPT9#10 JOB
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
/* care must be taken with recordsize */
DEFINE ALTERNATEINDEX -
(NAME(PLIVSAM.AJC1.SEXIND) -
VOLUMES(nnnnnn) -
TRACKS(4 1) -
KEYS(1 37) -
RECORDSIZE(20 400) -
NONUNIQUEKEY -
RELATE(PLIVSAM.AJC1.BASE))
/*
//STEP2 EXEC PGM=IDCAMS,REGION=512K
//DD1 DD DSNAME=PLIVSAM.AJC1.BASE,DISP=SHR
//DD2 DD DSNAME=PLIVSAM.AJC1.SEXIND,DISP=SHR
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
BLDINDEX INFILE(DD1) OUTFILE(DD2)
DEFINE PATH -
(NAME(PLIVSAM.AJC1.SEXPATH) -
PATHENTRY(PLIVSAM.AJC1.SEXIND))
//図 41 では、KSDS の固有キー代替索引パスを作成する方法を説明しています。 データ・セットは電話番号による索引付けが行われ、その番号をキーとして 使用することで、電話番号の持ち主の名前を検索することができるようになります。UNIQUEKEY を指定すると、キーを固有とすることができます。 また、どの番号が使用されていないかを示すために、 データ・セットを数値順にリストすることができます。 使用されるアクセス方式サービス・コマンドは以下の 3 つです。
代替索引データを保持するデータ・セットを定義します。
関連レコードへのポインターを代替索引に入れます。
PL/I ファイルを関連付けるエンティティーを、DD ステートメントで定義します。
DD ステートメントは、BLDINDEX の INFILE および OUTFILE、ならびに ソート・ファイルで必要です。組み込まれる名前を混同することがないようにしてください。
//OPT9#14 JOB
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DEFINE ALTERNATEINDEX -
(NAME(PLIVSAM.AJC2.NUMIND) -
VOLUMES(nnnnnn) -
TRACKS(4 4) -
KEYS(3 20) -
RECORDSIZE(24 48) -
UNIQUEKEY -
RELATE(PLIVSAM.AJC2.BASE))
/*
//STEP2 EXEC PGM=IDCAMS,REGION=512K
//DD1 DD DSNAME=PLIVSAM.AJC2.BASE,DISP=SHR
//DD2 DD DSNAME=PLIVSAM.AJC2.NUMIND,DISP=SHR
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
BLDINDEX INFILE(DD1) OUTFILE(DD2)
DEFINE PATH -
(NAME(PLIVSAM.AJC2.NUMPATH) -
PATHENTRY(PLIVSAM.AJC2.NUMIND))
//固有キーを使用して代替索引を作成する場合は、 同じ代替キーで他のレコードが組み込まれることがないようにしてください。 実際、固有キー代替索引は、電話帳として使用するには、完全に満足のいくものとはいえません。 なぜなら、固有キー代替索引では、2 人の人間が同じ番号を持つことができないためです。 同様に、基本キーでは 1 人の人間が 2 つの電話番号を持てません。 解決策として、ESDS に 2 つの非固有キー代替索引を持たせるか、 または 1 人の人間が複数の番号を持てるようにデータ・フォーマットを再構築して、 複数の番号に対応した非固有キー代替索引を 1 つ持たせるようにします。
代替索引パスを使用して VSAM データ・セットにアクセスしている場合は、SAMEKEY 組み込み関数を 使用して、非固有キーの有無を検出できます。非固有キーを検出した場合、SAMEKEY は、 検索されたレコードと同じ代替索引キーを持つレコードが他に存在するかどうかを示します。 このため、レコードの読み取りは、非固有キーを持つ一連のレコードの最後で停止して、 それ以降のレコードを読み取らないことがあります。SAMEKEY (ファイル参照) は、入出力ステートメントが正しく完了し、 アクセスしたレコードの次に、同じキーを持つ別のレコードが続く場合は '1'B を戻します。 そうでない場合は '0'B を戻します。
図 42 は、ESDS での代替索引の使用と、逆方向読み取りについて説明します。 このプログラムは以下の 4 つのファイルを使用します。
BASEFLE
基本データ・セットを順方向に読み取る。
BACKFLE
基本データ・セットを逆方向に読み取る。
ALPHFLE
名前によって子の索引付けを行う英字代替索引パス。
SEXFILE
子の性別に対応する代替索引パス。
すべてのファイルに DD ステートメントがあります。DSNAME パラメーターに基本データ・セット名を 指定して、BASEFLE と BACKFLE を基本データ・セットに接続し、図 39 と 図 40 で示したパス名を指定して ALPHFLE と SEXFILE を接続します。
プログラムではデータにアクセスするために SEQUENTIAL ファイルを使用し、 最初はそれを通常の順で書き込みし、それから逆順で書き込みします。AGEQUERY ラベルでは、固有代替索引の 代替索引キーに関連付けられたデータを読み取るために、DIRECT ファイルが使用されます。
最後に、SPRINT ラベルでは、非固有キー代替索引パスを使用して、 ファミリー内の女性のリストを書き込むために KEYED SEQUENTIAL ファイルが使用されます。 同じキーを持つすべてのレコードを読み取るために、SAMEKEY 組み込み関数が使用されます。 女性名は もともと入力された順でアクセスされます。これが行われるのは ファイルが順方向または逆方向に読み取られる場合です。 非固有キー・パスの場合は、BKWD オプションはキーの読み取り順にのみ影響します。 同じキーを持つ項目の順番はファイルが順方向に読み取られる場合と同じです。
削除: 例の終わりでは、 アクセス方式サービスの DELETE コマンドが基本データ・セットを削除するために使用されています。 これが行われると、関連する代替索引とパスも削除されます。
図 43 では、KSDS を更新するための、固有な代替索引キーを持つパスの使用法と 代替索引の順にそれにアクセスし出力する方法を説明します。
代替索引パスは、パスの名前 (PLIVSAM.AJC2.NUMPATH、図 41 の DEFINE PATH コマンドで指定されたもの) を DSNAME として 指定する DD ステートメントによって、PL/I ファイルに関連付けられています。
プログラムの最初のセクションでは、代替索引キーを使用して新規のレコードを挿入するために、DIRECT OUTPUT ファイルが使用されます。 代替索引を用いて変更を加える場合は、既存のレコードへのアクセス用の 基本キーや代替索引キーを変更しないでください。 また、 変更の際に、基本索引や固有キー代替索引に、重複するキーを追加しないでください。
プログラムの 2 番目のセクションでは (PRINTIT ラベルで)、 データ・セットが SEQUENTIAL INPUT ファイルを使用して代替索引キーの順で読み取られます。その後、SYSPRINT に書き込まれます。
//OPT9#15 JOB
//STEP1 EXEC IBMZCLG
//PLI.SYSIN DD *
READIT: PROC OPTIONS(MAIN);
DCL BASEFLE FILE SEQUENTIAL INPUT ENV(VSAM),
/*File to read base data set forward */
BACKFLE FILE SEQUENTIAL INPUT ENV(VSAM BKWD),
/*File to read base data set backward */
ALPHFLE FILE DIRECT INPUT ENV(VSAM),
/*File to access via unique alternate index path */
SEXFILE FILE KEYED SEQUENTIAL INPUT ENV(VSAM),
/*File to access via nonunique alternate index path */
STRING CHAR(80), /*String to be read into */
1 STRUC DEF (STRING),
2 NAME CHAR(25),
2 DATE_OF_BIRTH CHAR(2),
2 FILL CHAR(10),
2 SEX CHAR(1);
DCL NAMEHOLD CHAR(25),SAMEKEY BUILTIN;
DCL EOF BIT(1) INIT('0'B);
/*Print out the family eldest first*/
ON ENDFILE(BASEFLE) EOF='1'B;
PUT EDIT('FAMILY ELDEST FIRST')(A);
READ FILE(BASEFLE) INTO (STRING);
DO WHILE(¬EOF);
PUT SKIP EDIT(STRING)(A);
READ FILE(BASEFLE) INTO (STRING);
END;
CLOSE FILE(BASEFLE);
PUT SKIP(2);
/*Close before using data set from other file not
necessary but good practice to prevent potential
problems*/
EOF='0'B;
ON ENDFILE(BACKFLE) EOF='1'B;
PUT SKIP(3) EDIT('FAMILY YOUNGEST FIRST')(A);
READ FILE(BACKFLE) INTO(STRING);
DO WHILE(¬EOF);
PUT SKIP EDIT(STRING)(A);
READ FILE(BACKFLE) INTO (STRING);
END;
CLOSE FILE(BACKFLE);
PUT SKIP(2);
/*Print date of birth of child specified in the file
SYSIN*/
ON KEY(ALPHFLE) BEGIN;
PUT SKIP EDIT
(NAMEHOLD,' NOT A MEMBER OF THE SMITH FAMILY') (A);
GO TO SPRINT;
END;
AGEQUERY:
EOF='0'B;
ON ENDFILE(SYSIN) EOF='1'B;
GET SKIP EDIT(NAMEHOLD)(A(25));
DO WHILE(¬EOF);
READ FILE(ALPHFLE) INTO (STRING) KEY(NAMEHOLD);
PUT SKIP (2) EDIT(NAMEHOLD,' WAS BORN IN ',
DATE_OF_BIRTH)(A,X(1),A,X(1),A);
GET SKIP EDIT(NAMEHOLD)(A(25));
END;
SPRINT:
CLOSE FILE(ALPHFLE);
PUT SKIP(1);
/*Use the alternate index to print out all the females in the
family*/
ON ENDFILE(SEXFILE) GOTO FINITO;
PUT SKIP(2) EDIT('ALL THE FEMALES')(A);
READ FILE(SEXFILE) INTO (STRING) KEY('F');
PUT SKIP EDIT(STRING)(A);
DO WHILE(SAMEKEY(SEXFILE));
READ FILE(SEXFILE) INTO (STRING);
PUT SKIP EDIT(STRING)(A);
END;
FINITO:
END;
/*
//GO.BASEFLE DD DSN=PLIVSAM.AJC1.BASE,DISP=SHR
//GO.BACKFLE DD DSN=PLIVSAM.AJC1.BASE,DISP=SHR
//GO.ALPHFLE DD DSN=PLIVSAM.AJC1.ALPHPATH,DISP=SHR
//GO.SEXFILE DD DSN=PLIVSAM.AJC1.SEXPATH,DISP=SHR
//GO.SYSIN DD *
ANDY
/*
//STEP2 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DELETE -
PLIVSAM.AJC1.BASE
//
//OPT9#16 JOB
//STEP1 EXEC IBMZCLG,REGION.GO=256K
//PLI.SYSIN DD *
ALTER: PROC OPTIONS(MAIN);
DCL NUMFLE1 FILE RECORD DIRECT OUTPUT ENV(VSAM),
NUMFLE2 FILE RECORD SEQUENTIAL INPUT ENV(VSAM),
IN FILE RECORD,
STRING CHAR(80),
NAME CHAR(20) DEF STRING,
NUMBER CHAR(3) DEF STRING POS(21),
DATA CHAR(23) DEF STRING,
EOF BIT(1) INIT('0'B);
ON KEY (NUMFLE1) BEGIN;
PUT SKIP EDIT('DUPLICATE NUMBER')(A);
END;
ON ENDFILE(IN) EOF='1'B;
READ FILE(IN) INTO (STRING);
DO WHILE(¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT (STRING) (A);
WRITE FILE(NUMFLE1) FROM (STRING) KEYFROM(NUMBER);
READ FILE(IN) INTO (STRING);
END;
CLOSE FILE(NUMFLE1);
EOF='0'B;
ON ENDFILE(NUMFLE2) EOF='1'B;
READ FILE(NUMFLE2) INTO (STRING);
DO WHILE(¬EOF);
PUT SKIP EDIT(DATA)(A);
READ FILE(NUMFLE2) INTO (STRING);
END;
PUT SKIP(3) EDIT('****SO ENDS THE PHONE DIRECTORY****')(A);
END;
/*
//GO.IN DD *
RIERA L 123
/*
//NUMFLE1 DD DSN=PLIVSAM.AJC2.NUMPATH,DISP=OLD
//NUMFLE2 DD DSN=PLIVSAM.AJC2.NUMPATH,DISP=OLD
//STEP2 EXEC PGM=IDCAMS,COND=EVEN
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DELETE -
PLIVSAM.AJC2.BASE
//VSAM 相対レコード・データ・セット (RRDS) で使用できる ステートメントとオプションを、表 29 に示します。
|
有効ステートメント および必須オプション |
指定できるその他の オプション |
|
|---|---|---|
|
SEQUENTIAL OUTPUT BUFFERED |
WRITE FILE(file-reference) FROM(reference); LOCATE 基底付き変数 FILE(file-reference); |
KEYFROM(expression) または KEYTO(reference) SET(pointer-reference) |
|
SEQUENTIAL INPUT BUFFERED |
READ FILE(file-reference) INTO(reference); READ FILE(file-reference) SET(pointer-reference); READ FILE(file-reference);2 |
KEY(expression) または KEYTO(reference) KEY(expression) または KEYTO(reference) IGNORE(expression) |
|
SEQUENTIAL UPDATE BUFFERED |
READ FILE(file-reference) INTO(reference); READ FILE(file-reference) SET(pointer-reference); READ FILE(file-reference);2 WRITE FILE(file-reference) FROM(reference); REWRITE FILE(file-reference); DELETE FILE(file-reference); |
KEY(expression) または KEYTO(reference) KEY(expression) または KEYTO(reference) IGNORE(expression) KEYFROM(expression) または KEYTO(reference) FROM(reference) および/または KEY(expression) KEY(expression) |
|
DIRECT OUTPUT BUFFERED |
WRITE FILE(file-reference) FROM(reference) KEYFROM(expression); |
|
|
DIRECT INPUT BUFFERED |
READ FILE(file-reference) INTO(reference) KEY(expression); READ FILE(file-reference) SET(pointer-reference) KEY(expression); |
|
|
DIRECT UPDATE BUFFERED |
READ FILE(file-reference) INTO(reference) KEY(expression); READ FILE(file-reference) SET(pointer-reference) KEY(expression); REWRITE FILE(file-reference) FROM(reference) KEY(expression); DELETE FILE(file-reference) KEY(expression); WRITE FILE(file-reference) FROM(reference) KEYFROM(expression); |
|
|
注:
|
||
RRDS をロードするときには、OUTPUT 用の関連ファイルをオープンする必要が あります。DIRECT ファイルまたは SEQUENTIAL ファイルを使用します。
DIRECT OUTPUT ファイルの場合、各レコードは WRITE ステートメントの KEYFROM オプション 内の相対レコード番号 (つまりキー) で指定された位置に入れられます (VSAM データ・セットのキーを参照)。
SEQUENTIAL OUTPUT ファイルの場合、KEYFROM オプションの 指定の有無に関係なく WRITE ステートメントを使用します。KEYFROM オプションを指定すると、 レコードは指定されたスロット内に置かれ、 省略した場合は、レコードは 現在位置に続くスロット内に 置かれます。 レコードを昇順の相対レコード番号順に並べる必要はありません。KEYFROM オプションを省略しても、KEYTO オプションにより、 書き込まれたレコードの相対レコード番号を入手することができます。
KEYFROM オプションも KEYTO オプションも使わずに、RRDS を順次にロードする場合は、 ファイルは KEYED 属性を持っている必要はありません。
既にレコードが存在する位置にレコードをロードしようとすることは誤りです。 KEYFROM オプションを使用する場合は、KEY 条件が生じ、 それを省略する場合は ERROR 条件が発生します。
図 44 では、データ・セットは DEFINE CLUSTER コマンドで定義され、PLIVSAM.AJC3.BASE という名前が与えられます。 それが RRDS であるという事実は、NUMBERED キーワードによって判断されます。PL/I プログラムでは、データ・セットは DIRECT OUTPUT ファイルによってロードされ、 WRITE...FROM...KEYFROM ステートメントが使用されます。
データが順に並んでいてキーが順序どおりになっていれば、SEQUENTIAL ファイル を使用して、先頭からデータ・セットに書き込むことができたはずです。 この後レコードは、次に使用できるスロットに入れられ、該当する番号が付けられます。 各レコード用のキーの番号が、KEYTO オプションを使って戻されたはずです。
PL/I ファイルは、DEFINE CLUSTER コマンドで 指定された名前を DSNAME として使用する DD ステートメントによってデータ・セットへ関連付けられます。
//OPT9#17 JOB
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DEFINE CLUSTER -
(NAME(PLIVSAM.AJC3.BASE) -
VOLUMES(nnnnnn) -
NUMBERED -
TRACKS(2 2) -
RECORDSIZE(20 20))
/*
//STEP2 EXEC IBMZCBG
//PLI.SYSIN DD *
CRR1: PROC OPTIONS(MAIN);
DCL NOS FILE RECORD OUTPUT DIRECT KEYED ENV(VSAM),
CARD CHAR(80),
NAME CHAR(20) DEF CARD,
NUMBER CHAR(2) DEF CARD POS(21),
IOFIELD CHAR(20),
EOF BIT(1) INIT('0'B);
ON ENDFILE (SYSIN) EOF='1'B;
OPEN FILE(NOS);
GET FILE(SYSIN) EDIT(CARD)(A(80));
DO WHILE (¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT (CARD) (A);
IOFIELD=NAME;
WRITE FILE(NOS) FROM(IOFIELD) KEYFROM(NUMBER);
GET FILE(SYSIN) EDIT(CARD)(A(80));
END;
CLOSE FILE(NOS);
END CRR1;
/*
//GO.NOS DD DSN=PLIVSAM.AJC3.BASE,DISP=OLD
//GO.SYSIN DD *
ACTION,G. 12
BAKER,R. 13
BRAMLEY,O.H. 28
CHEESNAME,L. 11
CORY,G. 36
ELLIOTT,D. 85
FIGGINS.E.S. 43
HARVEY,C.D.W. 25
HASTINGS,G.M. 31
KENDALL,J.G. 24
LANCASTER,W.R. 64
MILES,R. 23
NEWMAN,M.W. 40
PITT,W.H. 55
ROLF,D.E. 14
SHEERS,C.D. 21
SURCLIFFE,M. 42
TAYLOR,G.C. 47
WILTON,L.W. 44
WINSTONE,E.M. 37
//RRDS にアクセスするのに使用する SEQUENTIAL ファイルは、INPUT 属性 または UPDATE 属性を使用してオープンすることができます。KEY、KEYTO、KEYFROM オプションのいずれかを使用する場合は、 属性 KEYED も指定する必要があります。
KEY オプションが指定されていない READ ステートメントの場合、レコードは、昇順の相対 レコード番号順に回復されます。 データ・セット内に空きスロットがあれば、すべてスキップされます。
KEY オプションを指定すると、READ ステートメントで回復されるレコードは、 指定した相対レコード番号を持つレコードになります。 このような READ ステートメントはデータ・セットを指定されたレコードに 位置付け、その後の順次読み取りは後続のレコードを順番に回復します。
KEYFROM オプションが指定されていても いなくても、WRITE ステートメントは、KEYED SEQUENTIAL UPDATE ファイル に使用することができます。 前回行ったアクセスの位置に関係なく、データ・セット内の任意の位置に 挿入を行うことができます。KEYFROM オプションが指定された WRITE ステートメントの場合、 そのデータ・セットに既に存在するレコードと同じ相対レコード番号 を持つレコードを挿入しようとすると、KEY 条件が発生します。KEYFROM オプションを省略すると、 現在位置から見て次のスロットにレコードが書き込まれます。 このスロットが空いていなければ、ERROR 条件が発生します。
KEYTO オプションを使えば、KEYFROM オプションを 指定していない WRITE ステートメントにより追加されるレコードのキーを回復することができます。
REWRITE ステートメントは、KEY オプションのあるなしに 関係なく、UPDATE ファイルで使用できます。KEY オプションを使用した場合、 再書き込みされるレコードは指定された相対レコード番号を持つ レコードであり、そうでない場合は直前の READ ステートメントによってアクセスされた レコードです。
DELETE ステートメントは、KEY オプションのあるなしに関係なく、 データ・セットにあるレコードを削除するのに使用することができます。
RRDS にアクセスするのに 使用する DIRECT ファイルは、OUTPUT 属性、INPUT 属性、UPDATE 属性を持つことができます。KEYED SEQUENTIAL ファイルを使用する場合と同様に、レコードの読み取り、書き込 み、再書き込み、または削除が行えます。
図 45 は、RRDS の更新の例を示しています。DIRECT UPDATE ファイルが使用され、 キーによって新しいレコードが書き込まれます。VSAM では空のレコードは使用できないため、レコードが空かどうかを検査する必要はありません。
ラベル PRINT で始まるプログラムの後半では、更新済みファイルが印刷されます。 ここでも、REGIONAL(1) にあるので、空のレコードの検査は必要ありません。
PL/I ファイルは、図 45 の DEFINE CLUSTER コマンド 内で定義された DSNAME の PLIVSAM.AJC3.BASE を指定する DD ステートメントで、 データ・セットと関連づけられます。
例の終わりに、DELETE コマンドを使ってデータ・セットの削除が示されています。
//* NOTE: WITH A WRITE STATEMENT AFTER THE DELETE FILE STATEMENT,
//* A DUPLICATE MESSAGE IS EXPECTED FOR CODE 'C' ITEMS
//* WHOSE NEWNO CORRESPONDS TO AN EXISTING NUMBER IN THE LIST,
//* FOR EXAMPLE, ELLIOT.
//* WITH A REWRITE STATEMENT AFTER THE DELETE FILE STATEMENT,
//* A NOT FOUND MESSAGE IS EXPECTED FOR CODE 'C' ITEMS
//* WHOSE NEWNO DOES NOT CORRESPOND TO AN EXISTING NUMBER IN
//* THE LIST, FOR EXAMPLE, NEWMAN AND BRAMLEY.
//OPT9#18 JOB
//STEP1 EXEC IBMZCBG
//PLI.SYSIN DD *
ACR1: PROC OPTIONS(MAIN);
DCL NOS FILE RECORD KEYED ENV(VSAM),NAME CHAR(20),
(NEWNO,OLDNO) CHAR(2),CODE CHAR(1),IOFIELD CHAR(20),
BYTE CHAR(1) DEF IOFIELD, EOF BIT(1) INIT('0'B),
ONCODE BUILTIN;
ON ENDFILE(SYSIN) EOF='1'B;
OPEN FILE(NOS) DIRECT UPDATE;
ON KEY(NOS) BEGIN;
IF ONCODE=51 THEN PUT FILE(SYSPRINT) SKIP EDIT
('NOT FOUND:',NAME)(A(15),A);
IF ONCODE=52 THEN PUT FILE(SYSPRINT) SKIP EDIT
('DUPLICATE:',NAME)(A(15),A);
END;
GET FILE(SYSIN) EDIT(NAME,NEWNO,OLDNO,CODE)
(COLUMN(1),A(20),A(2),A(2),A(1));
DO WHILE (¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT (' ',NAME,'#',NEWNO,OLDNO,' ',CODE)
(A(1),A(20),A(1),2(A(2)),X(5),2(A(1)));
SELECT(CODE);
WHEN('A') WRITE FILE(NOS) KEYFROM(NEWNO) FROM(NAME);
WHEN('C') DO;
DELETE FILE(NOS) KEY(OLDNO);
WRITE FILE(NOS) KEYFROM(NEWNO) FROM(NAME);
END;
WHEN('D') DELETE FILE(NOS) KEY(OLDNO);
OTHERWISE PUT FILE(SYSPRINT) SKIP EDIT
('INVALID CODE: ',NAME)(A(15),A);
END;
GET FILE(SYSIN) EDIT(NAME,NEWNO,OLDNO,CODE)
(COLUMN(1),A(20),A(2),A(2),A(1));
END;
CLOSE FILE(NOS);
PRINT:
PUT FILE(SYSPRINT) PAGE;
OPEN FILE(NOS) SEQUENTIAL INPUT;
EOF='0'B;
ON ENDFILE(NOS) EOF='1'B;
READ FILE(NOS) INTO(IOFIELD) KEYTO(NEWNO);
DO WHILE (¬EOF);
PUT FILE(SYSPRINT) SKIP EDIT(NEWNO,IOFIELD)(A(5),A);
READ FILE(NOS) INTO(IOFIELD) KEYTO(NEWNO);
END;
CLOSE FILE(NOS);
END ACR1;
/*
//GO.NOS DD DSN=PLIVSAM.AJC3.BASE,DISP=OLD
//GO.SYSIN DD *
NEWMAN,M.W. 5640C
GOODFELLOW,D.T. 89 A
MILES,R. 23D
HARVEY,C.D.W. 29 A
BARTLETT,S.G. 13 A
CORY,G. 36D
READ,K.M. 01 A
PITT,W.H. 55
ROLF,D.F. 14D
ELLIOTT,D. 4285C
HASTINGS,G.M. 31D
BRAMLEY,O.H. 4928C
//STEP3 EXEC PGM=IDCAMS,REGION=512K,COND=EVEN
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DELETE -
PLIVSAM.AJC3.BASE
//