For
For is used to perform loops in two cases:
* Read loops on database tables or joins.
* Loops on index values or on a list of values.
Syntax
(1) For INDEX_VARIABLE = FIRST_VALUE To LAST_VALUE STEP_CLAUSE
...
Next INDEX_VARIABLE
(2) For LIST_VARIABLE = LIST_OF_VALUES
...
Next LIST_VARIABLE
(3) For KEY_DESC HINT_CLAUSE FROM_TO_CLAUSE WHERE_CLAUSE WITH_CLAUSE
...
Next
(4) For (VARIA_LIST) From DATAB_TYPE Sql SQL_STATEMENT As [CLASS]
Next
Syntax 1:
INDEX_VARIABLEis a numeric value that will take its first value with the result ofFIRST_VALUEand then vary by steps given by theSTEP_CLAUSE(1 if noSTEP_CLAUSEexists) untilEND_VALUEhas been exceeded (the execution will continue after Next).FIRST_VALUEandEND_VALUEare numeric expressions that give the beginning and the end of the loop.STEP_CLAUSEis an optional clause that gives the step value of the loop, with the following syntax: StepSTEP_VALUE, whereSTEP_VALUEis a numeric expression that gives the value that increment the index variable at every loop.
Syntax 2:
LIST_VARIABLEis a variable that will successively take every loop all the values given inLIST_OF_VALUES.
Syntax 3:
KEY_DESCis a key description from a table or join, with the following syntax:ABBREVis the abbreviation of the table or the link in which the loop is performed (by default, the default table as indicated by File or DefaultFile).KEY_NAMEis the name of a key defined in the dictionary for the table, or given by an Order By syntax. By default, it is the default key as defined by currind.GROUPING_LEVELis the number of key components used in the loop. Every loop will take a different key value if you consider the number of elements given byGROUPING_LEVEL. By default, the loop will be done on every selected line of the database.- When the reckey keyword is used, no FROM_TO_CLAUSE is allowed.
HINT_CLAUSEis an optional clause that defines a hint sent to the database. If this clause is ommitted, the engine acts as if the WithNohint had been sent. For more information, see Hint.FROM_TO_CLAUSEgives a key range for a loop on a table, with the following syntax : FromKEY_VALUEToKEY_VALUE.KEY_VALUEis a list of at least one expression, separated by semicolons, that defines a value for the different segments of the key.WHERE_CLAUSEis an optional clause with the following syntax: WhereFILTER_EXPRESSION, WhereFILTER_EXPRESSIONis an expression that filters the lines in the database. For more information, see Where.WITH_CLAUSEis an optional clause that can have one of the two following syntaxes:
Syntax 4
This is declared in the following document.
Examples
# Example 1: loop on a value with step 1
Local Integer I,J
For I=1 To 10
J+=I
Next I
# At this point, I=11, and J=55
# Example 2: loop on a decimal value
Local Decimal NUMBER
Local Integer LOOP_COUNT
For NUMBER=pi To 10 Step pi
LOOP_COUNT+=1
Next NUMBER
# At this point, NUMBER is equal to 4*pi (the first value that exceeds 10) and LOOP_COUNT is equal to 3
# Example 3: descending loop
Local Integer DOWN, LOOP_COUNT
For DOWN=20 To 0 Step -4
LOOP_COUNT+=1
Next DOWN
# At this point, DOWN is equal to -4 and LOOP_COUNT is equal to 6
# Example 4: Loop that will never be executed
Local Integer I, STARTING_POINT,LOOP_COUNT
Gosub SET_STARTING_POINT
For I=STARTING_POINT To STARTING_POINT+3 Step -1
LOOP_COUNT+=1
Next I
# At this point, LOOP_COUNT is equal to 0: as the range is ascending and the step descending no loop will be performed
# Example 5: Compute the planning for the first, third and fourth weeks of every month except June and July
Local Char IMONTH(20)
Local Integer IWEEK
For IMONTH="January","February","March","April","May","September","October","November","December"
For IWEEK=1,3,4
Call GET_PLANNING(IWEEK,IMONTH)
Next IWEEK
Next IMONTH
# Example 6: Perform a loop for all the customers using the default key
Local File CUSTOMERS [CUST]
For [CUST]
Call SEND_GREETINGS_MAIL([CUST]CUSTOMER)
Next
# Example 7: Perform a loop for all the newly created customers using the default key
Local File CUSTOMERS [CUST]
For [CUST] Where CRDATTIM>=format$("4Y[-]MM[-]DD",date$-10)+"T00:00:00Z"
Call SEND_GREETINGS_MAIL([CUST]CUSTOMER)
Next
# Example 8: Perform a loop for all the customer having a category between 3 and 5
Local File CUSTOMERS [CUST] Order By Key CATEG=CATEGORY;CUSTOMER
For [CUST]CATEG From 3 To 5
Call SEND_ADVERTISING_MAIL([CUST]CUSTOMER)
Next
# Example 9: Perform a loop for all the customer having a category between 3 and 5
# Send them a letter depending on the country
Local File CUSTOMERS [CUST] Where find(COUNTRY,"FRANCE","GERMANY","ITALY")<>0
& Order By Key CATEG=CATEGORY;COUNTRY;CUSTOMER
For [CUST]CATEG(1) From 3 To 5
# We will enter in this loop for every distinct value of CATEG
For [CUST]CATEG(2)
# We will enter in this loop for a given CATEG value for every distinct value of COUNTRY
MODEL=string$(COUNTRY="FRANCE","FRENCH")+string$(COUNTRY="GERMANY","GERMAN")+string$(COUNTRY="ITALY","ITALIAN")
For [CUST]CATEG
# This loop is performed for every customer for the CATEG and COUNTRY selected in the nesting loops.
CALL SEND_MAIL(MODEL,[CUST]CUSTOMER)
Next
Next
Next
# Example 10 : Update in a loop with lock with 2 conditions, one given by evalue(CONDITION), the other by evalue(CONDITION1)
# Attention, this locks the whole set of data given by the first CONDITION until the commit or rollback is performed
Trbegin MYTABLE [MYT]
For [MYT] Where evalue(CONDITION) With Lock
If evalue(CONDITION1) : Gosub UPDATE_MYT : Rewrite [MYT]
Break (fstat<>0)
Next
If fstat : Rollback : Else : Commit : Endif
# Example 11: Perform a loop on all the lines of a table with no constraint on the reading order
For [MYT]reckey Where evalue(CONDITION)
...
Next
Description
For .. Next instructions define loops that can be nested, either on variables (syntax 1 and 2), or on database tables or joins (syntax 3).
The loop will terminate and the execution will continue after the Next instruction in the following cases:
* If a Break is found in the loop. BreakN allows to quit N nested For-Next, Repeat-Until, While-Wend loops.
* If the loop variable took a value out of the limits given by FIRST_VALUE and LAST_VALUE in syntax 1.
* If all the values found in the list have been successfully used in the loop execution (syntax 3).
* If all the lines satisfying the conditions and in the key range have been reached in the loop (syntax 3). The key range is defined when For are nested on successive partial keys to create breaks on these levels.
* In the ForWithLock syntax, encountering a locked line does not end the loop, but fstat will be set to 1 after the corresponding Next execution.
The final state after the Next is:
* The value of INDEX_VARIABLE, VALUE_VARIABLE, or the current record if a break was executed.
* The first value that is strictly greater or smaller than LAST_VALUE in syntax 1 (depending if the loop is ascending or descending).
* The last value in LIST_OF_VALUES for syntax 2.
* The last line read in the table or the join for syntax 3.
When the For instruction is executed, the following operations are performed:
* In syntax 1,FIRST_VALUE, LAST_VALUE and STEP_VALUE are evaluated:
* If STEP_VALUE is 0, an error is displayed.
* If (LAST_VALUE-FIRST_VALUE)*STEP_VALUE is negative, the loop is not executed, but INDEX_VARIABLE is assigned with FIRST_VALUE.
* INDEX_VARIABLE is assigned with FIRST_VALUE and the loop is executed:
* In syntax 2,VALUE_VARIABLE is assigned with the first value found in LIST_OF_VALUES.
* In syntax 3:
* If it is the unique loop done on the table or the first level of nesting, the SQL select is executed and a fetch is done to get the first line.
* On a nested For level (on the same table and the same index, with a breaking level B that is greater than the previous one), no read is done, but the breaking conditions for the next are set to the B first components of the key.
When the Next instruction is executed, the following operations are performed:
* In syntax 1,INDEX_VARIABLE is incremented by STEP_VALUE. If the value of INDEX_VARIABLE goes out of the range given by (FIRST_VALUE, LAST_VALUE), the loop ends, otherwise the loop continues.
* In syntax 2, if not all the values in LIST_OF_VALUES have been explored, the next value on the list will be assigned to INDEX_VARIABLE and the loop will continue, otherwise the loop ends.
* In syntax 3:
* If the For was done without BREAKING_LEVEL on the key, the next record will be fetched. If the end of the selection is reached, the loop ends, otherwise the loop will continue.
* If a value B is given for BREAKING_LEVEL, lines will be fetched until at least a value of the B segments of the key. If the end of the selection is reached, the loop ends, otherwise the loop stops.
If the loop continues, the execution continues with the instruction that follows the For instruction associated with the Next. If the loop stops, the execution continues with the instruction that follows the Next instruction.
Comments
For syntax 1
The loop variable cannot be modified inside the loop. Only the For instruction changes its value at every step. FIRST_VALUE, LAST_VALUE, and STEP_VALUE are also fixed to the value given when the For was executed and cannot be changed.
For syntax 3
The keys usable in a For are:
* When a table is used:
* The key defined by the Order By if there is one.
* The keys defined in the dictionary.
* When a join is used:
* The key defined by the Order By clause on the link or on the Filter if there is one.
* The key defined in the last Order By clause on the main table of the Link.
* The keys defined in the dictionary for the main table of the Link.
In a For loop where a BREAKING_LEVEL is given, the [G]currlen variable is set with the BREAKING_LEVEL value.
If the abbreviation or the key is omitted:
* The default file is used as defined by DefaultFile, or File.
* The default key is used:
* The last key used if another access was previously done.
* The key defined in the last Order By clause if there is one.
* The first key by default.
At the end of the loop, [S]fstat is set to 0 except if the end of the cursor was reached. [S]fstat will have a value set to 4.
When the For...With Lock syntax, the behavior might differ depending on the database:
* With oracle, the whole selection is locked immediately.
* With SQL server, the lines are locked successively and a locking issue will happen only when a locked line is encountered.
When a locking issue happens, new read attempts will be done after a waiting time until the lock is released. The use of For...With Lock is discouraged.
The WHERE_CLAUSE and the FROM_TO_CLAUSE can only be used in the first For of the nested For on different breaking levels of a key. For example:
# Case that will not work
Local File CUSTOMERS [CUST] Order By Key CATEG=CATEGORY;COUNTRY;CUSTOMER
For [CUST]CATEG(1) From 3 To 5 : # Allowed because it is the first level of the nesting
For [CUST]CATEG(2) Where find (COUNTRY,"FRANCE","USA")<>0 : # Syntax not allowed
For [CUST]CATEG
...
Next
Next
Next
# The right implementatipn
Local File CUSTOMERS [CUST] Order By Key CATEG=CATEGORY;COUNTRY;CUSTOMER
& Where find (COUNTRY,"FRANCE","USA")<>0 : # The filter is set first
For [CUST]CATEG(1) From 3 To 5 : # Allowed because it is the first level of the nesting
For [CUST]CATEG(2)
For [CUST]CATEG
...
Next
Next
Next
When
For is nested on a table and a key, the breaking levels indicated must be in increasing order. There is no constraint on the fact that they are consecutive. If no final For loop without breaking order exists, the lowest level of read will be grouped. For example, this is allowed: Local File MYTABLE [MYT] Order By Key MYKEY=A;B;C;D;E;F
# Loop on all distinct values of (A,B)
For [MYT]KEY(2)
# Loop on all distinct values of (C,D) for a given value of (A,B)
For [MYT]KEY(4)
...
Next
NextThere is a difference between Oracle and SQL server in the
For loop when lines are inserted between the range of the For during its execution:* With Oracle, the lines will not be visible.
* With SQL server, the lines will be visible, except if the clause WithStability dedicated to this situation is used (this makes the execution slower).
Associated errors
| Error code | Description |
|---|---|
| 7 | Class does not exist (syntax 3). |
| 10 | FIRST_VALUE, LAST_VALUE or STEP_VALUE are not numeric (syntax 1). |
| 10 | A value on the LIST_OF_VALUE is not consistent with the LIST_VARIABLE data type (syntax 2). |
| 32 | Bad nesting order of breaking levels (syntax 3). |
| 41 | The STEP_VALUE is 0 (syntax 1). |
| 43 | No more locks available (syntax 3). |
See also
To, Step, Next, Order By, reckey, Where, With, Lock, Stability, From, System, Hint, Nohint, Break.