The FOR EACH and FOR FIRST statements process a set of records (or a single record) from a VSAM file. The FOR construct is iterative. With each iteration, it returns the next record in the requested set. All of the statements in the scope of the FOR apply to each record selected. FOR FIRST and FOR EACH are the only constructs that update or delete a record.
This statement has the following format:
<<label>>
[EACH ]
FOR [ALL ] dataview_name[NO UPDATE]
[[THE] FIRST [n] ]
[WHERE where‑condition ]
[ORDERED BY [ASCENDING ] [FIELD‑NAME ]]
[ [DESCENDING] ]
statements
[WHEN NONE ]
[ statements]
[WHEN ERROR ]
[ statements]
ENDFOR
An optional 1‑ to 15‑character name of the FOR construct. You can use this label to refer to the construct in QUIT and PROCESS NEXT statements and as the operand of certain functions such as $COUNT.
Indicate that the statements in the scope of the FOR construct apply to every record that satisfies the where condition. You can use the reserved words EACH and ALL interchangeably.
Specifies that the statements in the scope of the FOR construct apply to the first n records that satisfy the where condition. The value specified for n can be a numeric literal or the name of a numeric field. The default is FIRST 1. You can add the reserved word THE for readability. When you use FOR FIRST n with a where condition and an ORDERED BY clause, all records that satisfy the where condition are ordered and then the first n ordered records are selected.
Specifies the name of the VSAM dataview.
Specifies that the records processed by this FOR construct are not updated. This applies even if the dataview is defined as updateable (Update Intent = Y in the parameter definition). If used, this clause must immediately follow the dataview name. The use of this clause for browsing provides significant efficiency gains.
Specifies that the statements in the scope of the FOR construct apply to those records that satisfy the specified condition. If the WHERE clause is omitted, all records in the data set are processed. The WHERE clause can also determine the index where the data set is accessed (see the description of the ORDERED BY clause for more detailed information).
A condition (as defined in the beginning of chapter 2) with the following further qualifications:
Identifies the index by which a KSDS data set is accessed and determines the logical order in which the records in any VSAM file are processed. If this clause is omitted, the index is determined as follows:
If the ORDERED BY clause is omitted and a WHERE clause is specified that uses more than one key, an error message is issued when the program is compiled.
Specifies whether processing proceeds from low to high values (ASCENDING) or high to low values (DESCENDING). ASCENDING is the default. The effect of ASCENDING/DESCENDING depends on the type of the VSAM data set:
Records are retrieved moving through the file in a forward (ASCENDING) or backward (DESCENDING) direction, according to the relative byte address (RBA). You cannot specify a field‑name to determine the order.
Records are retrieved according to the relative record number, moving from the lowest number to the highest (ASCENDING) or from the highest number to the lowest (DESCENDING). You cannot specify a field‑name to determine the order.
Records are retrieved according to ascending or descending values in the field specified as field‑name. Records are retrieved in collating sequence. If the specified field‑name identifies a signed numeric (type N) field, the collating sequence cannot return the records in the expected algebraic order.
The name of a field or group of fields defined as a primary or alternate key. You can only specify the field‑name for a KSDS file. You can specify only one field‑name. It cannot be subscripted.
PDL statements. The statements in the logical scope of a FOR construct can reference any field in the record most recently processed by the FOR. However, it is the programmer's responsibility to check the record type before referencing any fields in a variable‑segment record.
An optional postscript that specifies that when none of the records meets the where condition, the statements following the WHEN NONE execute.
Specifies statements to execute when a dataview error is encountered in the scope of the FOR construct. If WHEN ERROR is not specified, errors are processed by the user‑defined or default error procedure.
The statements specified following a WHEN ERROR clause can access $ERROR functions and should resolve the error with either a PROCESS NEXT or DO ERROR statement. If processing falls through to the ENDFOR, the $ERROR functions are no longer available.
Note: Only dataview errors are handled by the WHEN ERROR clause. System and internal errors are handled by the user‑specified or default error procedure.
A reserved word that marks the end of the FOR construct. If FOR statements are nested, the most recent undelimited FOR construct is delimited by the first occurrence of ENDFOR. Each FOR in a nested FOR construct must have a corresponding ENDFOR.
Updates are actually written to the file at the ENDFOR of the current iteration of the FOR construct.
You can reference fields processed by each iteration of the FOR construct in PDL statements. The identifier is the field name or the field name with the dataview name as qualifier. For example, the field ACCT‑NO in the ACCT dataview can be compared to the field ACCT‑NO in the panel named PNL1:
IF ACCT.ACCT‑NO EQ PNL1.ACCT‑NO ...
You cannot make such references before the FOR executes.
Sometimes it is convenient to first process a dataview record and then refers to its fields rather than coding the actions in the FOR. For example, you can delegate finding the appropriate record to a lower level procedure, as shown in following examples in this section.
Statements outside the logical scope of the FOR construct can access, but not update, data in the dataview record. Data in the last record processed is available after the ENDFOR until another FOR accesses the same dataview, except when the record was deleted or no records were found (WHEN NONE).
The access key used to retrieve records should not be updated in the scope of a FOR statement based on that key. If the access key is the primary key, VSAM does not allow you to change it. If the access key is an alternate key, you can update it in CA Ideal; however the results can be unpredictable:
You must make updates (changes and deletes) in the logical scope of the FOR. Any update of a dataview field in the scope of a FOR logically updates the file. For changes (but not for deletes), the actual update takes place at the ENDFOR for the current iteration. Therefore, any QUIT or PROCESS NEXT executed in the scope of a FOR abandons the update of the current record even for fields whose values already were changed. A checkpoint in the logical scope of the FOR does not commit the current update, because the update does not take place until the ENDFOR.
VSAM records are updated only through the primary index. Before updating a record, CA Ideal rereads the record with exclusive control, using the primary key. CA Ideal can then verify that the record was not deleted or changed since the original access before updating or deleting the record.
During updates, CA Ideal writes a record only when it can determine that the data was altered. CA Ideal always processes CHECKPOINT and BACKOUT requests, even if no actual changes were made to the file. In a CICS environment, the CHECKPOINT and BACKOUT statements execute the CICS SYNCPOINT and SYNCPOINT ROLLBACK commands. In non‑CICS environments, the BACKOUT statement has no effect. The CHECKPOINT statement performs a TCLOSE operation that flushes certain VSAM buffers if there was any VSAM access before the CHECKPOINT.
If statements outside the logical scope of the FOR construct attempt to update the record (with a SET, MOVE, and so on), a run‑time error results.
Make sure that the above actions do not occur in procedures or subprograms called from in the FOR construct.
In the scope of a FOR statement that accesses a VSAM data set, a non‑ideal subprogram should not access that VSAM data set or issue a CICS SYNCPOINT.
The FOR EACH and FOR FIRST statements read the set of records that satisfies the conditions specified in the WHERE clause and then process those records according to the statements entered in the FOR construct. If the WHERE clause is complex, the set of records to read is determined by establishing a search interval based on the conditions in the WHERE clause.
Conditions connected by an OR can result in an overly large search interval. For example, if the WHERE clause specifies the highest value of a key field and the lowest value of a key field, connected by an OR, the search interval includes the entire file.
You can nest any of the FOR constructs as long as each FOR construct refers to a different dataview. Do not nest a FOR construct for a given dataview in another FOR construct for the same dataview.
If more than one record in a file is needed simultaneously, either use two dataviews for the same file or save necessary information in working data.
When a QUIT is executed in the logical scope of a FOR, the next statement executed is the statement after the ENDFOR. When FOR and LOOP constructs are nested, any construct can be abandoned by referencing the optional label in a QUIT statement. See the QUIT statement in this chapter.
You can use the WHERE and ORDERED BY clauses in either order.
You cannot delete records from an ESDS file; therefore, you cannot specify the DELETE statement in a FOR construct that accesses an ESDS file.
When updating an ESDS data set, you cannot change the length of a record. With CA Ideal, you can decrease the logical length of a record (either by reducing the number of occurrences in a variable‑occurrence record or by changing the record to a shorter variable‑segment record with the SET $REC‑SEGMENT command), but the remaining length of the updated record is padded with binary zeros. Do not use this technique when record‑types are identified by record‑length since the original length is retrieved when the record is read.
You can improve efficiency in the following ways:
Examples
In the following example, assume that the BALANCE field is defined as an alternate key for the DELINQUENT‑ACCT dataview. Since the BALANCE field is used in the WHERE clause and there is no ORDERED BY clause, the BALANCE field is used as the access key.
FOR EACH DELINQUENT‑ACCT
WHERE BALANCE > 200
DO CONTACT‑COLLECTOR
ENDFOR
In the following example, the access key is determined by the ORDERED BY clause since neither the QOH nor the PRICE field are key fields.
FOR FIRST INVENTORY‑ITEM
WHERE QOH > 50 AND PRICE < 500
ORDERED BY ITEM‑NAME
DO PROCESS‑ITEM
ENDFOR
For the INVEN dataview used in the following example, the PRICE field is defined as an alternate key and is used as the access key, based on its use in the WHERE clause. Since PRICE is not a unique key, if the P‑5‑CHEAP‑ITEMS procedure includes an update or a TRANSMIT statement, processing cannot resume after the first iteration of the FOR and an error occurs.
FOR THE FIRST 5 INVEN
WHERE PRICE < 100
DO P‑5‑CHEAP‑ITEMS
ENDFOR
In the following example, the EMPLOYEE file is accessed using the unique key EMP‑NO; however, each record in the file is read in sequence to find the records that satisfy the WHERE clause, since the key field EMP‑NO is not specified in the WHERE clause. If EMP‑NO in the PAY‑REC dataview is also a key field, the PAY‑REC dataview is accessed randomly (only the record that matches the EMPLOYEE record is read).
FOR EACH EMPLOYEE
ORDERED BY EMP‑NO
WHERE DEPT = 'D'
FOR EACH PAY‑REC
WHERE PAY‑REC.EMP‑NO = EMPLOYEE.EMP‑NO
DO PROCESS‑PAY
ENDFOR
ENDFOR
The following example shows the use of the WHEN NONE clause and indicates when you can access and update dataview fields.
FOR FIRST ACCT
WHERE PAST‑DUE > 90
ORDERED BY ACCT‑NO
: you can refer to or update ACCT.field here
WHEN NONE
DO NO‑DELINQ‑ACCT
ENDFOR
: you can now refer to ACCT.field if present
: you cannot update ACCT.field here (unless this
: is a procedure performed by a DO statement
: in the FOR, but not in the WHEN NONE)
The following example shows the use of FOR statement is included in the procedure FIND‑CUSTOMER. You cannot update the record in the subsequent IF statement, although you can reference, display, or list the fields.
DO FIND‑CUSTOMER
IF CUST‑FOUND
: you can refer to "CUST.field" here
ELSE
DO CUST‑NOT‑FOUND
ENDIF
<<FIND‑CUSTOMER>> PROCEDURE
FOR THE FIRST CUST
WHERE CUST‑NO = TRANS‑CUST‑NO
SET CUST‑FOUND = TRUE
WHEN NONE
SET CUST‑FOUND = FALSE ENDFOR
In the following example, the PSS‑MASTER dataview is accessed by relative byte address using the $RBA function to determine the starting record. The dataview name is not specified for the function when it is used in the WHERE clause.
FOR FIRST 21 PSS‑MASTER
WHERE $RBA GE START‑ADDRESS :function is not qualified
statements
ENDFOR
SET LAST‑ADDRESS = $RBA(PSS‑MASTER) :function is qualified
In the following example, two FOR constructs were specified to retrieve the records that satisfy the condition EMP‑ID < 101 OR EMP‑ID > 846. In this example, the PSS‑MASTER file is a KSDS file with the key field EMP‑ID.
FOR EACH PSS‑MASTER
WHERE EMP‑ID < 101
statements
ENDFOR
FOR EACH PSS‑MASTER
WHERE EMP‑ID > 846
statements
ENDFOR
With the FOR EACH statement, the results of the two FOR statements above are the same as that for a single FOR EACH statement with the combined condition WHERE EMP‑ID < 101 OR EMP‑ID > 846. However, with a FOR FIRST statement, the results might not be the same since, with the single construct, only the first record that satisfies the combined condition is retrieved, but with a double construct, two records are retrieved.
In the following example, two FOR constructs access a weekly transaction file called TRAN‑FILE. The FOR FIRST construct loads an RBA table from the first record that contains the RBAs used for each day's transactions. The FOR EACH construct retrieves Tuesday's records by comparing the $RBA function to the RBA table values for Tuesday and Wednesday.
FOR FIRST TRAN‑FILE
SET W‑RBA‑TABLE = TRAN‑FILE.TABLE‑SEG BY NAME
ENDFOR
statements
FOR EACH TRAN‑FILE
WHERE $RBA GE W‑RBA‑TABLE.TUESDAY
AND $RBA LT W‑RBA‑TABLE.WEDNESDAY + 1
statements
ENDFOR
|
Copyright © 2015 CA Technologies.
All rights reserved.
|
|