Modifying Data: MATCH and NEXT

In this section:

The MATCH and NEXT statements are the core of MODIFY requests; they are the statements that determine which data source records are added, changed, or deleted. They work by selecting a particular segment instance, then updating or deleting it. They may also add new segment instances.

The MATCH statement selects specific segment instances based on their values. The NEXT statement selects the next segment instance after the current position.

The MATCH Statement

How to:

Reference:

The MATCH statement selects specific segment instances based on their values. It compares one or more field values in the instances with corresponding incoming data values. The action it performs depends on whether there is a segment instance with matching field values.

For example, suppose a MODIFY request was processing this incoming data record in comma-delimited format

EMP_ID = 123456789, CURR_SAL = 20000, $

and that the request contained this MATCH statement:

MATCH EMP_ID
  ON MATCH UPDATE CURR_SAL
  ON NOMATCH INCLUDE

This MATCH statement compares the EMP_ID value of an incoming data record to the EMP_ID values in segment instances:

Notice that the MATCH statement used each of the two incoming data fields differently. It used the EMP_ID field (specified after the word MATCH) to locate the segment instance (or to prove that it did not exist); it never altered the EMP_ID value in the segment. If it did locate the instance, it replaced the CURR_SAL value in the instance with the value in the incoming data field.

To identify the correct segment instance, the field values that the MATCH statement is searching for must be unique to the instance within its segment chain. For the most common types of segments, types S1 and SH1, the key field value is unique to each instance within its segment chain. This is the value you will usually be searching for.

Note that the MODIFY command cannot update key fields. To update key fields, use the FSCAN facility as described in Directly Editing FOCUS Databases With FSCAN.

Remember from the introduction that FOCUS executes a MODIFY request for every transaction.

Syntax: How to Use a MATCH Statement

MATCH {*  [KEYS]  [SEG n]|field1 [field2 field3 ... field-n]}
  ON MATCH action-1 
  ON NOMATCH action-2 
  [ON MATCH/NOMATCH action-3]

where:

field1 ...

Are the names of incoming data fields to be compared with similarly named data source fields. The names may be full field names, aliases, or truncations. If a field value is missing, the value is treated as zeros for numeric fields and blanks for alphanumeric fields.

These fields are segment key fields unless the MATCH statement is modifying a segment of type S0 or blank. If the segment is type Sn or SHn and you do not specify the segment keys, the request adds the keys to the list automatically and displays a warning message.

If the list of fields is too long to fit on one line, begin each line with the word MATCH. For example:

MATCH EMP_ID DAT_INC TYPE
MATCH PAY_DATE DED_CODE

To compare the values of all fields in the data source with incoming values, enter:

MATCH *

To compare the values of all key fields in the data source with incoming values, enter:

MATCH * KEYS

To compare the values of all key fields in a particular segment, type

MATCH * KEYS SEG n

where n is either the segment name or number as determined by the ? FDT query (described in the Developing Applications manual).

action-1

If the MATCH statement locates a segment instance with a data value matching the incoming data value (ON MATCH), it performs this action.

action-2

If the MATCH statement cannot locate a segment instance with a value matching the incoming data value (ON NOMATCH), it performs this action.

action-3

Whether or not the MATCH statement locates a segment instance with a value matching the incoming data value (ON MATCH/NOMATCH), it performs this action.

Note that you may include many ON MATCH and ON NOMATCH phrases in one MATCH statement. MATCH phrases can precede or follow NOMATCH phrases. The actions you may use in MATCH statements are listed in the section below. They fall into seven groups:

  • Actions that modify segments.
  • Actions that control MATCH processing.
  • Actions that read incoming data fields.
  • Actions that perform computations and validations or type messages to the terminal.
  • Actions that control Case Logic.
  • Actions that control multiple-record processing.
  • Actions that activate and deactivate fields.

Please note the following rules regarding the MATCH statement:

  • Each phrase of the MATCH statement must start on a separate line.
  • The ON MATCH and ON NOMATCH phrases may be reversed.
  • If an action has a list of fields, but the list of fields is too long to fit on one line, you may break the list into two or more lines. Begin each line with the ON MATCH or ON NOMATCH phrase, followed by the action. For example:
    MATCH EMP_ID
      ON NOMATCH REJECT
      ON MATCH UPDATE DEPARTMENT CURR_SAL
      ON MATCH UPDATE CURR_JOBCODE ED_HRS

Syntax: How to Specify Actions With the ON MATCH/NOMATCH Phrase

The MATCH statement has an ON MATCH/NOMATCH phrase. This phrase specifies an action to be taken regardless of whether the field value for which the MATCH statement is searching exists in the data source. This phrase is especially useful when you are using CRTFORMs with display or turnaround fields (see Designing Screens With FIDEL). For example:

MODIFY FILE EMPLOYEE
CRTFORM
 "ENTER EMPLOYEE'S ID: <EMP_ID"
MATCH EMP_ID
    ON MATCH/NOMATCH CRTFORM LINE 3
 "ENTER DEPARTMENT: <T.DEPARTMENT"
 "ENTER NEW SALARY: <T.CURR_SAL"
    ON MATCH UPDATE DEPARTMENT CURR_SAL
    ON NOMATCH INCLUDE
DATA VIA FI3270
END

This request prompts you for an employee's ID. It then searches for the ID in the data source. It prompts you for the employee's new department and salary, whether the ID is in the data source or not. If the ID is in the data source, it updates the employee's department and salary; otherwise, it adds a new segment instance with the information.

You could not have placed the CRTFORM statement before the MATCH statement, because the CRTFORM statement contains turnaround fields.

You can specify the following actions in an ON MATCH/NOMATCH phrase:

  • PROMPT
  • TED
  • CRTFORM
  • GOTO
  • IF
  • ACTIVATE
  • DEACTIVATE
  • REPEAT
  • HOLD

Note: TED in MODIFY can be used only with fields that have a text (TX) format (see Entering Text Data Using TED for entering and editing text fields with TED).

Reference: MATCH Statement Defaults

The following are defaults affecting the MATCH statement:

  • If a MODIFY request has neither MATCH nor NEXT statements, it defaults to:
    MATCH *
    ON NOMATCH INCLUDE

    It adds the instance even if another instance has the same key values. Since key values uniquely identify segments, you should avoid doing this unless you are loading data into a newly created data source, the incoming data is in a data source, and you know that there are no duplicate key values in the data.

    The following request reads in data from a fixed-format data source, ddname EMPDATA, to load in data into the segments EMPINFO and SALINFO in the EMPLOYEE data source:

    MODIFY FILE EMPLOYEE
    FIXFORM EMP_ID/9   LAST_NAME/15  FIRST_NAME/10
    FIXFORM PAY_DATE/I6     GROSS/D12.2
    DATA ON EMPDATA
    END
  • If a MATCH statement has neither an ON MATCH nor an ON NOMATCH phrase, the MATCH statement defaults to:
    ON MATCH CONTINUE 
    ON NOMATCH INCLUDE
  • If a MATCH statement has an ON NOMATCH phrase but no ON MATCH phrase, the ON MATCH phrase defaults to:
    ON MATCH CONTINUE
  • If a MATCH statement has a MATCH phrase but no NOMATCH phrase, the ON NOMATCH phrase defaults to:
    ON NOMATCH REJECT

    Note: If a MATCH statement has the phrase

    ON NOMATCH TYPE

    and no other ON NOMATCH phrases, the request automatically adds the phrase:

    ON NOMATCH REJECT

Adding, Updating, and Deleting Segment Instances

The most important function of the MATCH statement is the adding, updating, and deleting of segment instances. The MATCH statement does this by first searching a particular segment chain within a segment for specific instances (segment chains are groups of segment instances associated with an instance in the parent segment). The root segment contains just one segment chain; descendant segments are composed of many segment chains. How the MATCH statement selects segment chains in descendant segments is explained in Modifying Data: MATCH and NEXT.

The process can be summarized as follows:

  1. The MODIFY request reads a transaction. The transaction contains values that identify a particular segment instance. Usually, these are key field values.
  2. The MATCH statement searches the segment for an instance containing the key field values:

    If it is adding a new instance, it must confirm that the instance is not yet in the segment. Otherwise, it would be adding a duplicate instance.

    If it is updating or deleting an instance, it must first find the instance in the segment.

  3. The MATCH statement takes action depending on whether it found the instance or not. These actions are as follows:
ON NOMATCH INCLUDE

The instance is not yet in the segment. Therefore, the request creates a new instance using values in the transaction.

ON MATCH REJECT

The new instance already exists in the segment. Therefore, the request does not add the instance to the data source. Rather, it rejects the transaction.

ON MATCH UPDATE  
list 

The instance exists in the segment. Therefore, the request changes the values of the data source fields named in list to the values in the transaction.

ON MATCH DELETE

The instance exists in the segment. Therefore, the request deletes the instance, all its descendants, and any references to the deleted instances in the indexes.

ON NOMATCH REJECT

The instance cannot be found in the segment. Therefore, it cannot be changed or deleted. The request rejects the transaction.

Example: Adding Segment Instances

The syntax of a MATCH statement that adds segment instances is:

MATCH keyfield 
  ON MATCH REJECT
  ON NOMATCH INCLUDE

When you include a new instance, the request fills the instance with the transaction field values. If some segment fields are absent in the transaction, they become blank or zeros in the instance, or the MISSING symbol if the field is described with the MISSING=ON attribute (discussed in the Describing Data manual).

FOCUS determines the placing of the instance within a segment chain based on the current position. The current position is the position of the instance you last added to the chain.

When FOCUS adds the next instance to a keyed segment, it determines whether the instance goes before or after the current position based on the sort order of the segment. If the instance goes after the current position, FOCUS matches field values from the current position forward until it finds the proper place for the new instance. If the instance goes before the current position, FOCUS matches field values from the beginning of the chain forward until it finds the place for the new instance.

To increase efficiency, submit your transactions in the same sorted order as the segment (ascending order for Sn segments, descending order for SHn segments). This causes FOCUS to move through the chain in one direction only.

If you do not submit the transactions in sorted order, you may get this message:

WARNING..TRANSACTIONS ARE NOT IN SAME SORT ORDER AS FOCUS FILE
PROCESSING EFFICIENCY MAY BE DEGRADED

This condition indicates that data will not be loaded in an optimal manner.

The following request adds new instances to the root segment of the EMPLOYEE data source. The fields EMP_ID (the key field), LAST_NAME, and FIRST_NAME in the new instances are filled with incoming data values; the other fields are left zero or blank:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID LAST_NAME FIRST_NAME
MATCH EMP_ID
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

A sample execution might go as follows:

  1. The request prompts you for an employee's ID, last name, and first name.
  2. You enter ID 071382660, last name SMITH, and first name HENRY.
  3. The request determines whether ID 071382660 is in the segment. It is there, so the request rejects the transaction, displaying a message telling you so.
  4. The request prompts you again for an employee's ID, last name, and first name.
  5. You enter ID 123456789, last name SMITH, and first name HENRY.
  6. The request determines whether ID 123456789 is in the segment. It is not there, so the request adds a new segment instance, with 123456789 as the key value, SMITH in the LAST_NAME field, and HENRY in the FIRST_NAME field. All other fields in the instance are blanks and zeros.

Example: Updating Segment Instances

The syntax of a MATCH statement to update segment instances is

MATCH keyfield 
  ON MATCH UPDATE list 
  ON NOMATCH REJECT

where list is a list of data source fields to be updated using the values in the transaction. If the list of fields is too large to fit on one line, begin each line with the ON MATCH UPDATE phrase. For example:

ON MATCH UPDATE EMP_ID LN FN
ON MATCH UPDATE HDT DPT CSAL
ON MATCH UPDATE CJC OJT

To update all fields in a matched segment (except the key fields), type:

ON MATCH UPDATE * [SEG n]

Note: You cannot update key fields. To change key fields, use the FSCAN facility as described in Directly Editing FOCUS Databases With FSCAN.

The following request updates the salary (CURR_SAL field) for employees you specify:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID CURR_SAL
MATCH EMP_ID
  ON MATCH UPDATE CURR_SAL
  ON NOMATCH REJECT
DATA

A sample execution might go as follows:

  1. The request prompts you for an employee's ID and a new salary.
  2. You enter ID 123123123 and a salary of $20,000.
  3. The request searches the segment for ID 123123123 but cannot find the value. It rejects the transaction.
  4. The request prompts you again for an employee ID and new salary.
  5. You enter ID 071382660 and a salary of $20,000.
  6. The request finds ID 071382660 in the segment and changes the employee's salary to $20,000.

You can combine adding and updating operations in one MATCH statement:

MATCH keyfield 
  ON MATCH UPDATE field-1 field-2 ... field-n 
  ON NOMATCH INCLUDE

This statement searches for a segment instance with a key field value the same as the similarly named incoming field value. If it finds the instance, it updates the instance. If it cannot find the instance, it adds a new instance. For example:

MATCH EMP_ID
  ON MATCH UPDATE CURR_SAL
  ON NOMATCH INCLUDE

Example: Deleting Segment Instances

The syntax of the MATCH statement for deleting a segment instance is:

MATCH keyfield 
  ON MATCH DELETE
  ON NOMATCH REJECT

Note that the UPDATE action only updates fields when the transaction fields have values present.

This request deletes records of employees who have left the company:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON MATCH DELETE
  ON NOMATCH REJECT
DATA

A sample execution might go as follows:

  1. The request prompts you for an employee ID.
  2. You enter ID 987654321.
  3. The request cannot find ID 987654321 in the segment, so it rejects the transaction, displaying a message telling you so.
  4. The request prompts you for another employee ID.
  5. You enter ID 119329144.
  6. The request finds ID 1193291and so on44 and deletes all record of the employee from the data source. This includes the employee's instance in the root segment and all descendant instances (such as pay dates, addresses, and so on).

Performing Other Tasks Using MATCH

Reference:

You may specify actions in MATCH statements that can stand alone as statements elsewhere in the MODIFY request. These actions are: read incoming data, perform computations and validations, type messages, control Case Logic and multiple record processing, and activate and deactivate fields.

Note that the MATCH statement can perform several actions if the ON MATCH or ON NOMATCH condition occurs. To specify this, assign each action a separate ON MATCH or ON NOMATCH phrase. For example:

MATCH EMP_ID
  ON MATCH UPDATE CURR_SAL
  ON NOMATCH TYPE "EMPLOYEE ID NOT FOUND"
  ON NOMATCH REJECT

There are two ON NOMATCH phrases in this request: one specifies the TYPE action, the other the REJECT action. If you include a REJECT action, it must appear last; otherwise the request will terminate and generate an error message.

Reference: Reading Data

The following actions read incoming data. They work just as FIXFORM, FREEFORM, PROMPT, and CRTFORM statements:

FIXFORM list

Where list is a list of fields and formats. Reads in data from a fixed-format data source.

FREEFORM list

Where list is a list of incoming data fields. Reads in data from a comma-delimited data source.

PROMPT list

Prompts the user for data in fields named in list one field at a time.

CRTFORM

Prompts the user for data using the full-screen FIDEL facility. FIDEL is described in Designing Screens With FIDEL.

TED

Opens a temporary file for text field data entry using TED.

Reference: Computations, Validations, and Messages

The following actions perform calculations and validations and type messages. These actions work the same as the COMPUTE, VALIDATE, and TYPE statements:

COMPUTE

Performs computations.

VALIDATE

Performs validations.

TYPE [ON ddname]

Types messages to the terminal. When the ON ddname option is used, the messages are sent to a file defined by ddname.

Reference: Controlling Case Logic

The following actions control Case Logic. They are discussed in Branching to Different Cases: The GOTO, PERFORM, and IF Statements:

GOTO casename

Branches to another case named by casename.

PERFORM casename

Branches to another case named by casename, then returns to the PERFORM.

IF expression [THEN]
GOTO case1 
[ELSE GOTO case2];

If the expression is true, the request branches to the case named by case1; otherwise the request branches to case named by case2.

Reference: Controlling Multiple Record Processing

These actions control multiple-record processing and are described in The REPEAT Method:

REPEAT

Begins a REPEAT statement that executes a group of MODIFY statements repeatedly.

HOLD list

Where list is a list of data fields. Stores field values in a buffer.

Reference: Activating and Deactivating Fields

These actions activate and deactivate fields as described in Active and Inactive Fields:

ACTIVATE list

Activates fields named in list.

DEACTIVATE list

Deactivates fields named in list.

Place these statements within a MATCH statement if you want to run them only when the request can locate incoming values in the data source (or confirm that incoming values are not in the data source). This improves efficiency and makes the request logic more flexible.

Example: Using MATCH Actions in a Request

For example, assume you are designing a request to update employee salaries. Those employees who have spent more than 100 hours in class (the ED_HRS field) are granted an extra 3% bonus.

The particular data source you are updating only contains the records of a small number of company employees, but the transaction data source contains records for every employee in the company. If you place the COMPUTE statement calculating the bonuses by itself, it will calculate the bonus for every record in the transaction data source, whether or not the record will be accepted into the data source. Instead, use the COMPUTE statement as an ON MATCH option in a MATCH statement. COMPUTE will then calculate the bonus only for employees in the data source. The request is:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID CURR_SAL
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH COMPUTE
     CURR_SAL = IF D.ED_HRS GT 100 THEN CURR_SAL*1.03
                ELSE CURR_SAL;
  ON MATCH UPDATE CURR_SAL
DATA

Note the use of a D. prefixed field in the COMPUTE expression (D.ED_HRS). This field refers only to ED_HRS values in the data source. You may refer to data source fields when using statements in MATCH and NEXT statements or after them. The data source fields must either be in the segment instance you are modifying or in a parent instance along the segment path.

Modifying Segments in FOCUS Structures

How to:

Reference:

This section discusses how the MATCH command modifies segments other than the root segment. The section covers:

Reference: Modifying Unique Segments

Unique segments are segments that consist of only one instance for every parent instance. They are always descended from other segments, but may not have descendants themselves. Because unique segment instances are extensions of their parent instances, they have no key fields.

There are two methods of modifying unique segments:

  • The CONTINUE TO method allows you to add, update, and delete unique segment instances.
  • The WITH-UNIQUES method allows you to add and update unique segment instances, but not to delete them. However, the WITH-UNIQUES method is easier to use.

Syntax: How to Modify Segment Instances Using the CONTINUE TO Method

The CONTINUE TO method first locates the parent instance, then proceeds to the unique instance. The syntax of the MATCH command to modify unique segment instances using the CONTINUE TO method is:

MATCH keyfield 
  ON NOMATCH action-1 
  ON MATCH CONTINUE TO u-field 
  ON MATCH action-2 
  ON NOMATCH action-3

where:

keyfield

Is the key field of the parent segment instance.

action-1

Is the action the request performs if the parent instance cannot be found.

u-field

Is the name of any field in the unique child segment.

action-2

Is the action the request performs if a unique child instance exists.

action-3

Is the action the request performs if a unique child instance does not exist.

The actions that the request can perform are the same as those described in Adding, Updating, and Deleting Segment Instances and Performing Other Tasks Using MATCH. The MATCH and NOMATCH phrases that follow the ON MATCH CONTINUE TO phrase can be in either order.

This example illustrates how the request selects unique segment instances. The root segment of the EMPLOYEE data source, called EMPINFO, which contains employee IDs, has a unique child segment called FUNDTRAN that contains information on employee bank accounts where pay checks are to be directly deposited. Every EMPINFO instance that describes an employee with a direct deposit bank account has one child instance in the FUNDTRAN segment.

You could prepare the following MODIFY request to enter information on employees that just opened a direct-deposit account:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID BANK_NAME BANK_ACCT
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH CONTINUE TO BANK_NAME
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

A sample execution might go as follows:

  1. The request prompts for an employee ID, bank name, and bank account number.
  2. You enter employee ID 456456456, bank name BEST BANK, and bank account no. 235532.
  3. The request does not find employee ID 456456456, so it rejects the transaction.
  4. The request prompts you for another employee ID, bank name, and bank account number.
  5. You enter employee ID 071382660, bank name BEST BANK, and bank account no. 235532.
  6. The request finds ID 071382660. This employee has a segment recorded in the FUNDTRAN segment, meaning that the employee already has a direct-deposit bank account. The request rejects the transaction.
  7. The request prompts you for another employee ID, bank name, and bank account number.
  8. You enter employee ID 112847612, bank name BEST BANK, and bank account 235532.
  9. The request finds employee ID 112847612 but finds no instance recorded for the employee in the FUNDTRAN segment.
  10. The request records the bank name and bank account number in a new instance in the unique segment.

The following request updates direct-deposit account information:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID BANK_NAME BANK_ACCT
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH CONTINUE TO BANK_NAME
  ON MATCH UPDATE BANK_NAME BANK_ACCT
  ON NOMATCH REJECT
DATA

The following request deletes account information for employees who have closed their direct-deposit accounts:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH CONTINUE TO BANK_NAME
  ON MATCH DELETE
  ON NOMATCH REJECT
DATA

To modify multiple unique children of one instance using the CONTINUE TO method, use Case Logic as explained in Case Logic Applications.

Syntax: How to Process Unique Instances Using the WITH-UNIQUES Method

The WITH-UNIQUES method processes unique instances as extensions of their parents; that is, it considers a parent instance and its unique child as one instance. This method first searches for the parent instance. If it finds the parent, it can update the parent instance and create or update the unique child at the same time. If it does not find the parent, it can create the parent instance and the unique child at the same time.

The syntax for the MATCH statement using the WITH-UNIQUES method is

MATCH WITH-UNIQUES keyfield 
  ON MATCH action1 
  ON NOMATCH action2

where:

keyfield

Is the key field in the parent segment.

action1

Is the action performed if the MATCH statement locates the parent instance.

action2

Is the action performed if the MATCH statement does not locate the parent instance.

The MATCH statement can specify these actions:

  • The INCLUDE action, which creates a new parent instance and unique children instances for which there is incoming data.
  • The UPDATE action, which updates a parent instance and its unique children. If a child instance does not exist, FOCUS creates one.
  • The DELETE action, which deletes the parent instance and all children instances.
  • Actions that perform the functions listed in Performing Other Tasks Using MATCH.

Note that the WITH-UNIQUES method can add and update unique instances, but it cannot delete them without deleting the parent instance. To delete unique instances, use the CONTINUE TO method described in Modify Segment Instances Using the CONTINUE TO Method.

This MODIFY request adds information on new employees, including information on direct-deposit bank accounts. If an employee is already recorded in the data source, the request rejects the entire transaction. The request is:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID FIRST_NAME LAST_NAME
PROMPT BANK_NAME BANK_ACCT
MATCH WITH-UNIQUES EMP_ID
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

This MODIFY request updates employees' account information. If an employee just opened a direct-deposit account, the request automatically creates a new unique instance to record the information. The request is:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID BANK_NAME BANK_ACCT
MATCH WITH-UNIQUES EMP_ID
  ON NOMATCH REJECT
  ON MATCH UPDATE BANK_NAME BANK_ACCT
DATA

This request adds and updates employees' account information, whether or not the employees are new:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID LAST_NAME FIRST_NAME
PROMPT BANK_NAME BANK_ACCT
MATCH WITH-UNIQUES EMP_ID
  ON NOMATCH INCLUDE
  ON MATCH UPDATE BANK_NAME BANK_ACCT
DATA

Note that the WITH-UNIQUES method allows you to include and update the multiple unique children of one instance in one MATCH statement.

When using MATCH WITH-UNIQUES followed by ON MATCH COMPUTE, each computed field must have its own ON MATCH COMPUTE statement.

Modifying Segments

How to:

Reference:

The following examples show how to modify segements.

Example: Modifying Descendant Segments

Modifying descendant segments is similar to modifying the root segment, with one difference: when a MATCH statement searches a root segment for a key field value, it searches every instance of the segment. When the MATCH statement searches a descendant segment, however, it searches only the segment chain belonging to a particular parent instance. If the MATCH statement cannot find the key field value in this chain, it executes the ON NOMATCH phrase. To modify the chain, you must first identify the parent instance using a previous MATCH statement.

The following example illustrates this. The EMPLOYEE data source contains two segments: An EMPINFO segment containing employee IDs, and a child segment called SALINFO that keeps track of each employee's monthly pay. Each of these IDs has an instance in the SALINFO segment for each month that the employee worked (for example, an employee working for eight months has eight instances in the SALINFO segment).

To modify a June instance in the SALINFO segment, you must first identify which employee was paid in June. If the MODIFY request cannot find the June instance for one employee, it will execute the ON NOMATCH phrase even though a June instance exists for another employee.

This request adds a new monthly pay instance for each employee in the company. Note the word CONTINUE, which causes the request to proceed to the next MATCH statement (which adds the instances to the descendant segment) without taking any action. Also note that the phrase ON NOMATCH CONTINUE is illegal:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID PAY_DATE GROSS
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH CONTINUE
MATCH PAY_DATE
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

An execution might go as follows:

  1. The request prompts you for an employee ID, the date the employee was paid, and the gross earnings paid.
  2. You enter an employee ID 159159159, pay date 820831 (August 31, 1982), and gross earnings of $916.67.
  3. The request cannot find ID 159159159, so it rejects the transaction.
  4. The request prompts you for another employee ID, pay date, and gross earnings.
  5. You enter employee ID 071382660, pay date 820831, and gross earnings of $916.67.
  6. The request finds ID 071382660, and searches the SALINFO segment chain belonging to 071382660 for the pay date 820831.
  7. The request finds the pay date 820831 in the segment chain. Since the instance already exists, the request rejects the transaction.
  8. You enter employee ID 071382660, pay date 820930 (September 30, 1982), and gross earnings of $916.67.
  9. The request finds ID 071382660, and searches the SALINFO segment chain belonging to 071382660 for the pay date 820930.
  10. The request does not find pay date 820930 in the segment chain, so it includes a new instance in the SALINFO segment chain for pay date 820930 with gross earnings of $916.67.

If your request prompts for data (using either PROMPT or CRTFORM), it is better to prompt for the child key field values after the request locates the parent key field values. This spares the user from typing the child key if the request cannot locate the parent key. You can rewrite the previous request as:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH PROMPT PAY_DATE GROSS
MATCH PAY_DATE
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

You can also write the request to include a new EMPINFO segment instance and a new SALINFO instance if the employee's ID is not already there:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID PAY_DATE GROSS
MATCH EMP_ID
  ON NOMATCH INCLUDE
  ON MATCH CONTINUE
MATCH PAY_DATE
  ON NOMATCH INCLUDE
  ON MATCH REJECT
DATA

The first MATCH statement searches the EMPINFO statement for the employee ID that you entered. If it does not find the ID, the request creates a new EMPINFO segment instance with the new ID, and a descendant SALINFO instance with the pay date and monthly pay you entered.

Note that when an INCLUDE action creates a new segment instance, it also creates all descendant instances for which data is present.

If the employee ID is already in the data source, the second MATCH statement searches the SALINFO segment for the pay date you entered. If it does not find the ID, the request creates a new SALINFO instance with the pay date. If the pay date is already in the segment, the request rejects the transaction.

This request updates monthly pay instances:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH PROMPT PAY_DATE GROSS
MATCH PAY_DATE
  ON MATCH UPDATE GROSS
  ON NOMATCH REJECT
DATA

This request deletes monthly pay instances:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH PROMPT PAY_DATE
MATCH PAY_DATE
  ON MATCH DELETE
  ON NOMATCH REJECT
DATA

You may combine the MATCH statements in the request into one statement. This is called matching across segments. To match across segments, specify the key fields that the request must search for from the root segment down to the descendant segment (in that order) after the MATCH keyword. For example, the request above that updates employee's monthly pay can be rewritten this way:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID PAY_DATE GROSS
MATCH EMP_ID PAY_DATE
  ON NOMATCH REJECT
  ON MATCH UPDATE GROSS
DATA

This is the request shown earlier in this section that adds data on new employees and employees' monthly pay:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID PAY_DATE GROSS
MATCH EMP_ID
  ON MATCH CONTINUE
  ON NOMATCH INCLUDE
MATCH PAY_DATE
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

This request can be rewritten this way:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID PAY_DATE GROSS
MATCH EMP_ID PAY_DATE
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

Note: When a MATCH statement matches across segments, the explicit ON MATCH and ON NOMATCH phrases in the statement are only executed for the last descendant segment (key field PAY_DATE in the example). For the other segments, the request executes default phrases. If you are updating or deleting instances, these phrases are:

ON MATCH CONTINUE
ON NOMATCH REJECT

If, for example, you include an ON NOMATCH TYPE phrase in the MATCH statement, the phrase only types a message when there is an ON NOMATCH condition on the last segment.

If you are adding new instances, the default phrases are:

ON MATCH CONTINUE
ON NOMATCH INCLUDE

Because of these defaults, use this technique only when you are confident that you understand the logic of the request.

Example: Modifying FOCUS Structures of Three or More Levels

What has been said for two-level FOCUS structures is true for three or more levels. To modify a descendant segment instance, you must first identify the parent instances to which the descendant instance belongs, from the root segment down to the immediate parent segment (the descendant segment instance belongs to a parent instance, that instance belongs to grandparent instance, and so on up the FOCUS structure to one of the root instances).

The following request illustrates this. The SALINFO segment has a child segment called DEDUCT that records all the different deductions that are taken from each monthly wage. If four deductions are taken from a monthly pay, that pay has four instances in the DEDUCT segment. The key field in the DEDUCT segment is DED_CODE; it specifies the type of deduction, such as certain taxes. The amount of the deduction is contained in the field DED_AMT.

MODIFY FILE EMPLOYEE
PROMPT EMP_ID PAY_DATE DED_CODE DED_AMT
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH CONTINUE
MATCH PAY_DATE
  ON NOMATCH REJECT
  ON MATCH CONTINUE
MATCH DED_CODE
  ON NOMATCH REJECT
  ON MATCH UPDATE DED_AMT
DATA

Example: Modifying Sibling Segments (Multi-Path Data Sources)

If you are modifying sibling segments (segments that have a common parent), place the MATCH statements modifying the siblings in any order after the MATCH statement identifying the parent instance. Each sibling must have a separate MATCH statement. If you are modifying descendants of one of the siblings, the MATCH statements that modify the children should follow immediately after the MATCH statement that identifies the sibling.

The following request updates the SALINFO and ADDRESS segments, both children of the EMPINFO segment. The ADDRESS segment contains both home and bank addresses of the employees; its key field is TYPE, which indicates whether the address is a home address or a bank address.

The request is as follows:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH PROMPT PAY_DATE GROSS TYPE ADDRESS_LN1
MATCH PAY_DATE
  ON NOMATCH REJECT
  ON MATCH UPDATE GROSS
MATCH TYPE
  ON NOMATCH REJECT
  ON MATCH UPDATE ADDRESS_LN1
DATA

Syntax: How to Modify Segments With No Keys

Segments of types S0 and blank (SEGTYPE= ,) have no key fields. Segments of type blank are always descendant segments; they can never be root segments. Segments of type S0 can be root segments.

To modify these segments, the MATCH statement selects instances by comparing the values of one or more fields in the segment to a similarly named transaction field. The MATCH statement has the form

MATCH {* [SEG n]|field-1 field-2 ... field-n}
  ON MATCH action-1 
  ON NOMATCH action-2

where:

field-1 ...

Are any fields in the segment you are modifying.

* SEG n

Matches all fields in the segment, where n is either the segment name or number as determined by the ? FDT query (described in the Developing Applications manual).

The difference between segment type S0 and blank is in the way FOCUS adds new instances to the segments.

Example: Storing Data With Type S0 Segments

When you add a segment instance to a type S0 segment, FOCUS matches field values in the segment chain from the current position forward through the chain, inserting the instance in the chain based on ascending order. FOCUS does not search the chain from the beginning; therefore, if the instance belongs before the current position, FOCUS inserts the instance at the end of the chain (this means that if you are adding instances to a new segment chain, FOCUS stores the instances in the order of submission). It may insert the instance even if another instance has the same field values and you specified ON MATCH REJECT. If, however, you sort the transactions in ascending sequence before submitting them, you will preserve the correct sequence in the chain. You will also prevent adding duplicate segments unless you specify ON MATCH INCLUDE.

Because it is difficult to ensure that segments of type S0 do not have instances with duplicate field values, they are difficult to maintain. You should only use them for data that needs to be loaded in once and does not need to be changed or deleted.

This is a sample FOCUS data source that stores memos, called MEMO. The Master File is:

FILE=MEMO ,SUFFIX=FOC ,$
SEGMENT=MEMOSEG  ,SEGTYPE=S1 ,$
 FIELD=MEMO_NAME ,ALIAS=MEMO ,FORMAT=A25      ,$
SEGMENT=TEXTSEG  ,SEGTYPE=S0 ,PARENT=MEMOSEG  ,$
 FIELD=LINE      ,ALIAS=LN   ,FORMAT=A70      ,$

The following request enters ten-line memos into the data source:

MODIFY FILE MEMO
PROMPT MEMO_NAME 10 (LINE)
MATCH MEMO_NAME
  ON MATCH REJECT
  ON NOMATCH INCLUDE
MATCH LINE
  ON MATCH INCLUDE
  ON NOMATCH INCLUDE
DATA

Note: The INCLUDE action in both ON MATCH and ON NOMATCH phrases adds a line of text even if the line is the same as another line in the memo (which would happen if you have more than one blank line in the memo) in all circumstances.

Reference: Type Blank Segments

When you add an instance to a type blank segment, the MODIFY request compares the instance you are adding to every instance in the segment chain, based on the fields you specify in the MATCH statement. Thus, if you specified the ON MATCH REJECT phrase in the MATCH statement, the request does not allow you to add an instance that has the same field values you are matching on as another instance.

You modify type blank segments the same way you modify other segments. Be careful, however, that the fields you are matching on uniquely identify the segment instances, or you may not be able to select the instance you want to modify. (MODIFY requests always select the first instance that fulfills the match conditions.)

Example: Modifying Segments With Multiple Keys

Segments may have multiple keys. These segments are types Sn or SHn where n is the number of keys. For example, a segment in ascending order that has two keys is type S2; that is, it has the attribute SEGTYPE=S2 in the Master File. Multiple keys are necessary when the first field alone cannot uniquely identify a segment instance. For example, a segment has three fields as described by the Master File:

FILE=ADDRESS ,SUFFIX=FOC ,$
   SEGMENT=ADDRSEG ,SEGTYPE=S2 ,$
    FIELD=LAST_NAME   ,ALIAS=LNAME  ,FORMAT=A15 ,$
    FIELD=FIRST_NAME  ,ALIAS=FNAME  ,FORMAT=A15 ,$
    FIELD=ADDRESS     ,ALIAS=ADDR   ,FORMAT=A80 ,$

Since LAST_NAME field is not enough to identify individual segment instances (some people share the same last name), the segment uses the first two fields, LAST_NAME and FIRST_NAME, as keys.

Note that multiple keys must always be the first fields in the segment, and they must be next to each other; that is, a non-key field cannot be between two key fields.

Modifying segments with multiple key fields is the same as modifying segments with one key field. The one difference is that you must specify all the key fields in the MATCH phrase.

To enter data into the ADDRESS data source, you prepare the following MODIFY request:

MODIFY FILE ADDRESS
PROMPT LAST_NAME FIRST_NAME ADDRESS
MATCH LAST_NAME FIRST_NAME
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

A sample execution might go as follows:

  1. The request prompts you for the last name, first name, and address.
  2. You enter last name FOX, first name GEORGE, and address 2365 N. HAMPTON ST. HAMILTON, MN 55473.
  3. The request searches the segment for an instance with both last name FOX and first name GEORGE.
  4. The request does not find such an instance, so it creates a new instance for George Fox.

Note that you cannot update any of the key fields.

Syntax: How to Use Alternate File Views

To modify descendant segments, you must first specify the parent segments using a series of MATCH statements. You can modify a descendant segment directly by declaring the segment to be the root segment of an alternate file view. To do this, the segment must fulfill three conditions:

  • The segment must be type S1 or SH1.
  • The key field must be indexed.
  • The key field values should be unique throughout the data source.

To declare an alternate file view, you begin the MODIFY request this way

MODIFY FILE filename.field

where:

filename

Is the name of the FOCUS data source you are modifying.

field

Is the name of the indexed key field in the root segment of the alternate file view.

Note that you can only update the root segment of the alternate file view; you cannot add or delete segment instances. However, you can add, update, and delete segment instances in the descendants of this segment. In addition, you may make use of external indices only using the FIND and LOOKUP functions. Be aware that an external index cannot be used as an entry point. For example,

MODIFY FILE filename.field

will be ineffective. FIND and LOOKUP are described in Special Functions.

This sample FOCUS data source, called BANK, contains information on bank accounts. The Master File is:

FILE=BANK ,SUFFIX=FOC ,$
SEGMENT=CUSTSEG ,$
  FIELD=SOC SEC NUM   ,ALIAS=SSN      ,FORMAT=A9   ,$
  FIELD=NAME          ,ALIAS=NAME     ,FORMAT=A30  ,$
SEGMENT=ACCTSEG ,SEGTYPE=S1 ,PARENT=CUSTSEG        ,$
  FIELD=ACCT NUM      ,ALIAS=ACCOUNT  ,FORMAT=A10  ,
  FIELDTYPE=I                                      ,$
FIELD=AMOUNT          ,ALIAS=AMOUNT   ,FORMAT=D10.2,$
SEGMENT=TRANSSEG ,SEGTYPE=S1 ,PARENT=ACCTSEG       ,$
  FIELD=TRANSNUM      ,ALIAS=TNUM     ,FORMAT=I5   ,$
  FIELD=TRANTYPE      ,ALIAS=TTYPE    ,FORMAT=A1   ,$
  FIELD=TR_AMOUNT     ,ALIAS=TAMOUNT  ,FORMAT=D8.2 ,$

This Description contains three segments:

  • The CUSTSEG segment contains social security numbers and names of bank depositors.
  • The ACCTSEG segment, child of CUSTSEG, contains account numbers and the amount of money in each account. Note that the field ACCT_NUM is indexed and that each account number is unique throughout the data source.
  • The TRANSSEG segment, child of ACCTSEG, contains information on individual bank account transactions: the transaction serial number (TRANSNUM), the type of transaction (TRANTYPE, which contains a D for deposits and a W for withdrawals), and the amount of the transaction (TR_AMOUNT).

To add new account information in the BANK data source, prepare the following MODIFY request:

MODIFY FILE BANK
PROMPT SSN NAME ACCT_NUM AMOUNT
MATCH SSN
  ON NOMATCH INCLUDE
  ON MATCH CONTINUE
MATCH ACCT_NUM
  ON NOMATCH INCLUDE
  ON MATCH REJECT
DATA

The MODIFY request above first specifies the parent segment CUSTSEG (MATCH SSN) before the child segment ACCTSEG (MATCH ACCT_NUM). Since ACCTSEG is an S1 segment with an indexed key field (ACCT_NUM), you can modify the ACCTSEG directly with this request:

MODIFY FILE BANK.ACCT_NUM
PROMPT ACCT_NUM AMOUNT
MATCH ACCT_NUM
  ON NOMATCH REJECT
  ON MATCH UPDATE AMOUNT
DATA

You may modify the root segment of the alternate file view and its descendants in the original data source structure, but not its parents. In the BANK data source, you may modify the TRANSSEG segment using the above alternate file view but not the CUSTSEG segment.

This request adds information on new bank account transactions to the data source:

MODIFY FILE BANK.ACCT_NUM
PROMPT ACCT_NUM AMOUNT PROMPT TRANSNUM TRANTYPE TR_AMOUNT
MATCH ACCT_NUM
  ON NOMATCH REJECT
  ON MATCH UPDATE AMOUNT
MATCH TRANSNUM
  ON MATCH REJECT
  ON NOMATCH INCLUDE
DATA

Selecting the Instance After the Current Position: The NEXT Statement

How to:

The NEXT statement selects the next segment instance after the current position, making the instance the new current position. The current position depends on the execution of MATCH and NEXT statements:

The NEXT statement can modify segment instances similarly to the MATCH statement and follows the same rules (see The MATCH Statement). However, the NEXT statement is most often used for displaying data source values.

Syntax: How to Use a NEXT Statement

The syntax of the NEXT statement is

NEXT field 
  ON NEXT action-1 
  ON NONEXT action-2

where:

field

Is any field in the segment whose instances are being selected.

action-1

Is the action the request takes if there is a next instance to select.

action-2

Is the action the request takes if it has reached the end of the segment chain.

There can be many ON NEXT and ON NONEXT phrases in a single NEXT statement. Each phrase specifies one action.

An action can be any action that is legal in the MATCH statement (see Adding, Updating, and Deleting Segment Instances and Performing Other Tasks Using MATCH). However, use ON NEXT INCLUDE and ON NONEXT INCLUDE phrases only to add instances to segments of type S0 or blank. If you use these phrases to modify other segments, you may duplicate what is already there. The difference between the two phrases is:

  • ON NEXT INCLUDE adds a new segment instance after the current position.
  • ON NONEXT INCLUDE adds a new instance at the end of the segment chain. The phrase ON NEXT INCLUDE is only valid for segments with type S0 or blank.

The following phrases are always illegal:

ON NONEXT UPDATE
  ON NONEXT DELETE
  ON NONEXT CONTINUE
  ON NONEXT CONTINUE TO

This phrase is legal even in requests that do not involve Case Logic:

ON NONEXT GOTO EXIT

The phrase terminates the request when the NEXT statement reaches the end of the segment chain.

Note that a NEXT statement can have multiple ON NEXT and ON NONEXT phrases. For example, the following statement displays the salaries of every employee in the data source and shows what their salaries would be if they are granted a 5% increase:

NEXT EMP_ID
  ON NEXT COMPUTE NEWSAL = 1.05 * D.CURR_SAL;
  ON NEXT TYPE
     "EMPLOYEE <D.EMP_ID SALARY NOW:<D.CURR_SAL"
     "SALARY PLUS 5% INCREASE: <NEWSAL"
  ON NONEXT TYPE
     "END OF EMPLOYEE FILE"
  ON NONEXT GOTO EXIT

Example: Selecting Instances

You can use NEXT statements in non-Case Logic requests to modify or display the data in:

  • The entire root segment.
  • The first instances of segment chains in descendant segments.

To modify or display data in entire descendant segment chains, you must use Case Logic as described in Case Logic Applications.

The NEXT statement can modify and display data in the root segment. This request displays all the employee IDs in the employee ID segment:

MODIFY FILE EMPLOYEE
NEXT EMP_ID
  ON NEXT TYPE "EMPLOYEE ID: <D.EMP_ID"
  ON NONEXT GOTO EXIT
DATA

When a NEXT statement modifies or displays data in a descendant segment, it can do so only to the first instance in a segment chain. Consider the following request:

MODIFY FILE EMPLOYEE
PROMPT EMP_ID
MATCH EMP_ID
  ON NOMATCH REJECT
  ON MATCH TYPE "YOU ENTERED ID <EMP_ID"
NEXT PAY_DATE
  ON NEXT TYPE
     "THIS EMPLOYEE'S LAST PAY DATE"
     "WAS <D.PAY_DATE"
  ON NONEXT GOTO EXIT
DATA

The MATCH statement selects an instance with a particular employee ID. The NEXT statement selects the instance with the employee's last pay date (the pay dates are organized in the data source from high to low). The PAY_DATE segment is a child of the EMP_ID segment.

The NEXT statement is at its most powerful when it is used to browse through an entire chain. To browse through a chain in a descendant segment, you must use Case Logic, as described in Case Logic Applications.

Displaying Unique Segments

How to:

You can use the NEXT statement to display and modify the contents of unique segments using two methods (see Modifying Segments in FOCUS Structures):

Syntax: How to Use the CONTINUE TO Method

The syntax of the CONTINUE TO method is

NEXT field 
  ON NONEXT action-1 
  ON NEXT CONTINUE TO u-field 
     ON NEXT action-2 
     ON NONEXT action-3

where:

field

Is the first field in the parent instance.

action-1

Is the action the request performs if there are no more instances in the parent segment chain.

u-field

Is the name of any field in the unique child segment.

action-2

Is the action the request performs if the parent instance has a unique child instance.

action-3

Is the action the request performs if the parent instance does not have a unique child instance.

Syntax: How to Use the WITH-UNIQUES Method

The syntax of the WITH-UNIQUES method is

NEXT WITH-UNIQUES field 
  ON NONEXT action1 
  ON NEXT action2

where:

field

Is the name of any field in the parent segment.

action1

Is the action the request performs if there are no more instances in the chain.

action2

Is the action the request performs if there is a next instance in the chain. This action can be performed on either the parent instance or the unique instance. If an UPDATE action updates a unique instance that does not exist yet, FOCUS creates the instance.


Information Builders