This document describes how the execution of a statement can be made dependent on a control break, and how control breaks can be used for the evaluation of Natural system functions.
The following topics are covered:
A control break occurs when the value of a control field changes.
The execution of statements can be made dependent on a control break.
A control break can also be used for the evaluation of Natural system functions.
System functions are discussed in System Variables and System Functions. For detailed descriptions of the system functions available, refer to the System Functions documentation.
With the statement AT
BREAK
, you specify the processing which is to be performed
whenever a control break occurs, that is, whenever the value of a control field
which you specify with the AT BREAK
statement changes. As a
control field, you can use a database field or a user-defined variable.
The following topics are covered below:
The field specified as control field in an
AT BREAK
statement is
usually a database field.
Example:
... AT BREAK OF DEPT statements END-BREAK ...
In this example, the control field is the database field
DEPT
; if the value of the field changes, for example,
FROM
SALE01
to SALE02
, the
statements specified in the AT BREAK
statement would be executed.
Instead of an entire field, you can also use only part of a field as a
control field. With the slash-n-slash notation
/n/
, you can determine that only the
first n positions of a field are to be checked for a
change in value.
Example:
... AT BREAK OF DEPT /4/ statements END-BREAK ...
In this example, the specified statements
would only be executed if the value of the first 4 positions of the field
DEPT
changes, for example, FROM SALE
to
TECH
; if, however, the field value changes from
SALE01
to SALE02
, this would be ignored and no
AT BREAK
processing performed.
** Example 'ATBREX01': AT BREAK OF (with database field) ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 NAME 2 CITY 2 COUNTRY 2 JOB-TITLE 2 SALARY (1:1) END-DEFINE * READ (5) MYVIEW BY CITY WHERE COUNTRY = 'USA' DISPLAY CITY (AL=9) NAME 'POSITION' JOB-TITLE 'SALARY' SALARY(1) /* AT BREAK OF CITY WRITE / OLD(CITY) (EM=X^X^X^X^X^X^X^X^X^X^X^) 5X 'AVERAGE:' T*SALARY AVER(SALARY(1)) // COUNT(SALARY(1)) 'RECORDS FOUND' / END-BREAK /* AT END OF DATA WRITE 'TOTAL (ALL RECORDS):' T*SALARY(1) TOTAL(SALARY(1)) END-ENDDATA END-READ END
In the above program, the first WRITE
statement is executed
whenever the value of the field CITY
changes.
In the AT
BREAK
statement, the Natural system functions
OLD
,
AVER
and
COUNT
are
evaluated (and output in the WRITE
statement).
In the AT END OF
DATA
statement, the Natural system function
TOTAL
is
evaluated.
Output of Program ATBREX01:
Page 1 04-12-14 14:07:26 CITY NAME POSITION SALARY --------- -------------------- ------------------------- ---------- AIKEN SENKO PROGRAMMER 31500 A I K E N AVERAGE: 31500 1 RECORDS FOUND ALBUQUERQ HAMMOND SECRETARY 22000 ALBUQUERQ ROLLING MANAGER 34000 ALBUQUERQ FREEMAN MANAGER 34000 ALBUQUERQ LINCOLN ANALYST 41000 A L B U Q U E R Q U E AVERAGE: 32750 4 RECORDS FOUND TOTAL (ALL RECORDS): 162500
A user-defined variable can
also be used as control field in an AT
BREAK
statement.
In the following program, the user-defined variable
#LOCATION
is used as control field.
** Example 'ATBREX02': AT BREAK OF (with user-defined variable and ** in conjunction with BEFORE BREAK PROCESSING) ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 CITY 2 COUNTRY 2 JOB-TITLE 2 SALARY (1:1) * 1 #LOCATION (A20) END-DEFINE * READ (5) MYVIEW BY CITY WHERE COUNTRY = 'USA' BEFORE BREAK PROCESSING COMPRESS CITY 'USA' INTO #LOCATION END-BEFORE DISPLAY #LOCATION 'POSITION' JOB-TITLE 'SALARY' SALARY (1) /* AT BREAK OF #LOCATION SKIP 1 END-BREAK END-READ END
Output of Program ATBREX02:
Page 1 04-12-14 14:08:36 #LOCATION POSITION SALARY -------------------- ------------------------- ---------- AIKEN USA PROGRAMMER 31500 ALBUQUERQUE USA SECRETARY 22000 ALBUQUERQUE USA MANAGER 34000 ALBUQUERQUE USA MANAGER 34000 ALBUQUERQUE USA ANALYST 41000
As explained
above,
the notation /n/
allows some portion of
a field to be checked for a control break. It is possible to combine several
AT BREAK
statements,
using an entire field as control field for one break and part of the same field
as control field for another break.
In such a case, the break at the lower level (entire field) must be
specified before the break at the higher level (part of field); that is, in the
first AT BREAK
statement the entire field must be specified as
control field, and in the second one part of the field.
The following example program illustrates this, using the field
DEPT
as well as the first 4 positions of that field (DEPT
/4/
).
** Example 'ATBREX03': AT BREAK OF (two statements in combination) ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 NAME 2 JOB-TITLE 2 DEPT 2 SALARY (1:1) 2 CURR-CODE (1:1) END-DEFINE * READ MYVIEW BY DEPT STARTING FROM 'SALE40' ENDING AT 'TECH10' WHERE SALARY(1) GT 47000 AND CURR-CODE(1) = 'USD' /* AT BREAK OF DEPT WRITE '*** LOWEST BREAK LEVEL ***' / END-BREAK AT BREAK OF DEPT /4/ WRITE '*** HIGHEST BREAK LEVEL ***' END-BREAK /* DISPLAY DEPT NAME 'POSITION' JOB-TITLE END-READ END
Output of Program ATBREX03:
Page 1 04-12-14 14:09:20 DEPARTMENT NAME POSITION CODE ---------- -------------------- ------------------------- TECH05 HERZOG MANAGER TECH05 LAWLER MANAGER TECH05 MEYER MANAGER *** LOWEST BREAK LEVEL *** TECH10 DEKKER DBA *** LOWEST BREAK LEVEL *** *** HIGHEST BREAK LEVEL ***
In the following program, one blank line is output whenever the value
of the field DEPT
changes; and whenever the value in the first 4
positions of DEPT
changes, a record count is carried out by
evaluating the system function COUNT
.
** Example 'ATBREX04': AT BREAK OF (two statements in combination) ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 DEPT 2 REDEFINE DEPT 3 #GENDEP (A4) 2 NAME 2 SALARY (1) END-DEFINE * WRITE TITLE '** PERSONS WITH SALARY > 30000, SORTED BY DEPARTMENT **' / LIMIT 9 READ MYVIEW BY DEPT FROM 'A' WHERE SALARY(1) > 30000 DISPLAY 'DEPT' DEPT NAME 'SALARY' SALARY(1) /* AT BREAK OF DEPT SKIP 1 END-BREAK AT BREAK OF DEPT /4/ WRITE COUNT(SALARY(1)) 'RECORDS FOUND IN:' OLD(#GENDEP) / END-BREAK END-READ END
Output of Program ATBREX04:
** PERSONS WITH SALARY > 30000, SORTED BY DEPARTMENT ** DEPT NAME SALARY ------ -------------------- ---------- ADMA01 JENSEN 180000 ADMA01 PETERSEN 105000 ADMA01 MORTENSEN 320000 ADMA01 MADSEN 149000 ADMA01 BUHL 642000 ADMA02 HERMANSEN 391500 ADMA02 PLOUG 162900 ADMA02 HANSEN 234000 8 RECORDS FOUND IN: ADMA COMP01 HEURTEBISE 168800 1 RECORDS FOUND IN: COMP
Automatic break processing is in effect for a processing loop which
contains an AT BREAK
statement. This applies to the following statements:
The value of the control field specified with the
AT BREAK
statement is
checked only for records which satisfy the selection criteria of both the
WITH
clause
and the WHERE
clause.
Natural system
functions (AVER
,
MAX
,
MIN
,
etc.) are evaluated for each record after all statements within the processing
loop have been executed. System functions are not evaluated for any record
which is rejected by WHERE
criteria.
The figure below illustrates the flow logic of automatic break processing.
The following example shows the use of the
Natural system functions
OLD
,
MIN
,
AVER
,
MAX
,
SUM
and
COUNT
in an
AT BREAK
statement
(and of the system function TOTAL
in an
AT END OF DATA
statement).
** Example 'ATBREX05': AT BREAK OF (with system functions) ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 NAME 2 CITY 2 SALARY (1:1) 2 CURR-CODE (1:1) END-DEFINE * LIMIT 3 READ MYVIEW BY CITY = 'SALT LAKE CITY' DISPLAY NOTITLE CITY NAME 'SALARY' SALARY(1) 'CURRENCY' CURR-CODE(1) /* AT BREAK OF CITY WRITE / OLD(CITY) (EM=X^X^X^X^X^X^X^X^X^X^X^X^X^X^X) 31T ' - MINIMUM:' MIN(SALARY(1)) CURR-CODE(1) / 31T ' - AVERAGE:' AVER(SALARY(1)) CURR-CODE(1) / 31T ' - MAXIMUM:' MAX(SALARY(1)) CURR-CODE(1) / 31T ' - SUM:' SUM(SALARY(1)) CURR-CODE(1) / 33T COUNT(SALARY(1)) 'RECORDS FOUND' / END-BREAK /* AT END OF DATA WRITE 22T 'TOTAL (ALL RECORDS):' T*SALARY TOTAL(SALARY(1)) CURR-CODE(1) END-ENDDATA END-READ END
Output of Program ATBREX05:
CITY NAME SALARY CURRENCY -------------------- -------------------- ---------- -------- SALT LAKE CITY ANDERSON 50000 USD SALT LAKE CITY SAMUELSON 24000 USD S A L T L A K E C I T Y - MINIMUM: 24000 USD - AVERAGE: 37000 USD - MAXIMUM: 50000 USD - SUM: 74000 USD 2 RECORDS FOUND SAN DIEGO GEE 60000 USD S A N D I E G O - MINIMUM: 60000 USD - AVERAGE: 60000 USD - MAXIMUM: 60000 USD - SUM: 60000 USD 1 RECORDS FOUND TOTAL (ALL RECORDS): 134000 USD
See the following example program:
With the BEFORE BREAK
PROCESSING
statement, you can specify statements that are to
be executed immediately before a control break; that is, before the value of
the control field is checked, before the statements specified in the
AT BREAK
block are
executed, and before any Natural system
functions are evaluated.
** Example 'BEFORX01': BEFORE BREAK PROCESSING ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 NAME 2 FIRST-NAME 2 SALARY (1:1) 2 BONUS (1:1,1:1) * 1 #INCOME (P11) END-DEFINE * LIMIT 5 READ MYVIEW BY NAME FROM 'B' BEFORE BREAK PROCESSING COMPUTE #INCOME = SALARY(1) + BONUS(1,1) END-BEFORE /* DISPLAY NOTITLE NAME FIRST-NAME (AL=10) 'ANNUAL/INCOME' #INCOME 'SALARY' SALARY(1) (LC==) / '+ BONUS' BONUS(1,1) (IC=+) AT BREAK OF #INCOME WRITE T*#INCOME '-'(24) END-BREAK END-READ END
Output of Program BEFORX01:
NAME FIRST-NAME ANNUAL SALARY INCOME + BONUS -------------------- ---------- ------------ ----------- BACHMANN HANS 56800 = 52800 +4000 ------------------------ BAECKER JOHANNES 81000 = 74400 +6600 ------------------------ BAECKER KARL 52650 = 48600 +4050 ------------------------ BAGAZJA MARJAN 152700 = 129700 +23000 ------------------------ BAILLET PATRICK 198500 = 188000 +10500 ------------------------
With automatic break processing, the statements specified in an
AT BREAK
block are
executed whenever the value of the specified control field changes - regardless
of the position of the AT BREAK
statement in the processing
loop.
With a PERFORM BREAK
PROCESSING
statement, you can perform break processing at a
specified position in a processing loop: the PERFORM BREAK
PROCESSING
statement is executed when it is encountered in the
processing flow of the program.
Immediately after the PERFORM BREAK PROCESSING
, you specify
one or more AT BREAK
statement blocks:
... PERFORM BREAK PROCESSING AT BREAK OF field1 statements END-BREAK AT BREAK OF field2 statements END-BREAK ...
When a PERFORM BREAK PROCESSING
is executed, Natural checks
if a break has occurred; that is, if the value of the specified control field
has changed; and if it has, the specified statements are executed.
With PERFORM BREAK PROCESSING
, system functions are
evaluated before Natural checks if a break has occurred.
The following figure illustrates the flow logic of user-initiated break processing:
** Example 'PERFBX01': PERFORM BREAK PROCESSING (with BREAK option ** in IF statement) ************************************************************************ DEFINE DATA LOCAL 1 MYVIEW VIEW OF EMPLOYEES 2 NAME 2 DEPT 2 SALARY (1:1) * 1 #CNTL (N2) END-DEFINE * LIMIT 7 READ MYVIEW BY DEPT AT BREAK OF DEPT /* <- automatic break processing SKIP 1 WRITE 'SUMMARY FOR ALL SALARIES ' 'SUM:' SUM(SALARY(1)) 'TOTAL:' TOTAL(SALARY(1)) ADD 1 TO #CNTL END-BREAK /* IF SALARY (1) GREATER THAN 100000 OR BREAK #CNTL PERFORM BREAK PROCESSING /* <- user-initiated break processing AT BREAK OF #CNTL WRITE 'SUMMARY FOR SALARY GREATER 100000' 'SUM:' SUM(SALARY(1)) 'TOTAL:' TOTAL(SALARY(1)) END-BREAK END-IF /* IF SALARY (1) GREATER THAN 150000 OR BREAK #CNTL PERFORM BREAK PROCESSING /* <- user-initiated break processing AT BREAK OF #CNTL WRITE 'SUMMARY FOR SALARY GREATER 150000' 'SUM:' SUM(SALARY(1)) 'TOTAL:' TOTAL(SALARY(1)) END-BREAK END-IF DISPLAY NAME DEPT SALARY(1) END-READ END
Output of Program PERFBX01:
Page 1 04-12-14 14:13:35 NAME DEPARTMENT ANNUAL CODE SALARY -------------------- ---------- ---------- JENSEN ADMA01 180000 PETERSEN ADMA01 105000 MORTENSEN ADMA01 320000 MADSEN ADMA01 149000 BUHL ADMA01 642000 SUMMARY FOR ALL SALARIES SUM: 1396000 TOTAL: 1396000 SUMMARY FOR SALARY GREATER 100000 SUM: 1396000 TOTAL: 1396000 SUMMARY FOR SALARY GREATER 150000 SUM: 1142000 TOTAL: 1142000 HERMANSEN ADMA02 391500 PLOUG ADMA02 162900 SUMMARY FOR ALL SALARIES SUM: 554400 TOTAL: 1950400 SUMMARY FOR SALARY GREATER 100000 SUM: 554400 TOTAL: 1950400 SUMMARY FOR SALARY GREATER 150000 SUM: 554400 TOTAL: 1696400