FORF

Sommaire


"For" permet de réaliser des boucles de lecture sur une table.

(Pour les boucles d'affectation d'une variable, se reporter à la documentation de l'instruction notée For(variable)).

 

Syntaxe

 
Syntaxe 1
 
Forclé1 [hint-cl]] [Fromclé_deb] [Toclé_fin ] [where-cl] [With Lock |With Stability ]
 
    ..... instructions
 
  Next [ clé ]
 

 

Paramètres

Elément

Description

Restrictions

clé1

Désignation de la clé d'un fichier utilisée pour l'ordre de tri, sous l'une des formes :

  • classe
  • classe id_clé1
  • classe id_clé '(' exp_ind ')'
  • reckey

classe désigne l'abréviation du fichier qui doit être ouvert

id_clé1

nom_de_variable désignant la clé

Aucune.

exp_ind

Expression entière du nombre de parties de clés utilisées. Par défaut, toute la clé est utilisée.

0 <=exp_ind<= nombre de composantes de la clé (au plus 8).

hint_cl

Voir instruction Hint

Aucune.

clé_deb

Clé de début de parcours, sous la forme d'une liste d'expressions séparées par le caractère ';' correspondant aux valeurs des sous-clés.

Le nombre d'expressions est au plus égal au nombre de composantes de la clé.

clé_fin

Clé de fin de parcours, sous la forme d'une liste d'expressions séparées par le caractère ';' correspondant aux valeurs des sous-clés.

Le nombre d'expressions est au plus égal au nombre de composantes de la clé.

where_cl

Voir instruction Where

Aucune.

 

Exemples

# chargement à l'écran de tous les champs saisissables d'un masque
For [AMZ]CODE Where CODMSK=[M]MASQUE & SAIAFF=1 &CODTYP<>"ABS"
    If !find([F:AMZ]CODZON,[M]ZONE(0..NOL-1))
        [M]ZONE(NOL) = [F:AMZ]CODZON
        Call TEXTE([F:AMZ]INTIT,[M]INTIT(NOL)) From OBJDIV
        [M]CODCTL(NOL) = [F:AMZ]CODCTL
        NOL += 1
    Endif
Next

 

Description et commentaires

"For" permet de faire des boucles de lecture sur une table selon une clé donnée.

L'instruction :

For clé From clé_deb To clé_fin Where expr_l
....
Next

est équivalente à :

Read clé >= clé_deb
While [S]fstat <= 2 and clé <= clé_fin
If expr_l
....
Endif
Read Next
Wend

... mais est beaucoup plus rapide sur une table Oracle.

L'instruction Next est logiquement équivalente à une suite de "Read clé Next" (ou Unlock [FIC] suivis de "Readlock" si on utilise la clause With Lock) tant que la valeur de clé de l'enregistrement lu est identique sur le nombre de parties de clés données. Si la clé est donnée sans précision d'un nombre de composantes, l'instruction Next est équivalente à un seul Read Next (ou Readlock).

Dans le cas où "For" comporte une condition portant sur une expression logique, Adonix peut être amené à faire de façon interne, des Read Next supplémentaires jusqu'à ce que l'expression soit satisfaite.

On peut imbriquer des boucles "For" sur le nombre de parties de la clé, de façon à définir des ruptures, à condition toutefois de respecter le nombre de ses composantes.

Les clés utilisables dans "For" sont :

Lorsqu'on utilise l'abréviation de lien (définie lors d'un Link précédent) dans un "For", Adonix essaie de lire un enregistrement du fichier principal selon la clé donnée dans l'instruction "For", puis un enregistrement dans chaque fichier lié selon la clé et le mode de lecture donnés dans Link.

La lecture d'un enregistrement, avec la précision d'une partie de clé, positionne automatiquement la variable [G]currlen ; Cette variable contient en effet, le nombre de partie de clé utilisée ; Attention, toute lecture suivante, sans précision de clé, s'effectuera sur la même partie de clé. Pour lire sur une clé entière, préciser la clé ou bien positionner la variable [G]currlen  à la valeur 0. La valeur 0 est la valeur par défaut.

On peut omettre dans la syntaxe de "For" l'abréviation du fichier ou le nom de la clé :

On peut utiliser la variable reckey à la place du nom de la clé :

On sort d'une boucle "For" si :

On ne sort pas d'une boucle "For ... With Lock" si on rencontre un enregistrement verrouillé, par contre la variable [S]fstat sera positionnée à 1 juste après Next.

En sortie de boucle, [S]fstat est positionné à 0 sauf lorsqu'on a atteint la fin du fichier, quand il n'y a plus d'enregistrements vérifiant la clause Where ou de clé inférieure ou égale à clé_fin. Dans ces cas [S]fstat vaudra 4.

En sortie de boucle l'enregistrement courant est le dernier parcouru. Ceci reste vrai pour la syntaxe avec verrouillage, l'enregistrement résultant pouvant être verrouillé ou pas.

Le "For ... With Lock" :

 

Remarque

Sous Oracle, les temps de réponse dépendant surtout du nombre de requêtes passées au serveur. Chaque ordre Read génère une requête SQL de type "select". Il en est de même pour chaque boucle For (de premier niveau). Dans ce cas une sorte d'index est créé sur les enregistrements sélectionnés rendant les accès suivants quasiment instantanés. Il faut donc utiliser les boucles "For" aussi souvent que possible.

Une requête est d'autant plus longue que le nombre d'enregistrements à explorer est grand. La clause Where (que ce soit sur un Filter placé avant ou sur l'ordre For lui-même) permet de limiter cette recherche.

Exemple :

soit un fichier de commandes client d'abréviation [CCL] ayant une clé CLICCL dont les deux premières parties sont CODCCL et DATCCL. On cherche à lire les clients entre 2 dates.
Si on fait :

For [CCL]CLICCL(1)
# beaucoup d'enregistrements seront sélectionnés.
[L]CLICUR = [F:CCL]CODCLI
For [CCL]CLICCL
If DATCCL >= DATDEB & DATCCL <= DATFIN
... etc ...

Il faut faire :

Filter [CCL] Where DATCCL >= DATDEB and DATCCL <= DATFIN
# on élimine toutes les commandes hors date dès le début.
For [CCL]CLICCL(1)
For [CCL]CLICCL

Dans le même esprit (et avec le même fichier) :

For [CCL]CLICCL From [L]CLICUR To [L]CLICUR
etFor [CCL]CLICCL Where CODCLIF = [L]CLICUR

sont deux syntaxes équivalentes (et efficaces).

Il est interdit de d'utiliser la clause Where (ou From to) à l'intérieur d'une boucle For et portant sur la même table. Il faut utiliser les tests If classiques si nécessaire.

Ne jamais initier une transaction par Trbegin (portant sur un fichier de la boucle) dans une boucle For With Lock, car sous Oracle, un seul enregistrement pourrait être lu.

Si la boucleFor With Lock est faite à l'intérieur d'une transaction, les enregistrements ne seront déverrouillés qu'après Commit. En dehors d'une transaction, l'enregistrement verrouillé parFor ... With Lock est déverrouillé par Next. Ce n'est pas le cas sous Oracle. Il faudra garder à l'esprit que les verrous sont une ressource limitée. Se reporter à la documentation sur l'instructionReadlock pour plus de détails.

 

Sous DB2, il existe une limite sur le nombre de champs restitués par une requête. La lecture d'un fichier dépassant 255 colonnes provoque une erreur, y compris la lecture d'un fichier lié. Nous n'avons pas de problème sur la définition de la table, puisque lors de la saisie des champs, il existe déjà ce contrôle. Par contre, le problème se pose sur la lecture basée sur une abréviation issue de l'instruction Link. La solution est de filtrer les champs nécessaires par l'instruction Columns.

  # Filtre de colonnes sur la classe issue du link
  Local File ORDERS [ORD]
  Local File ITMMASTER [ITM]
  Link [ORD] with [ITM]ITM0=[F:ORD]ITMREF as [ORI]
  # Position du filtre sur la réf.article, la dés. article, le n° d'ordre
  Columns [ORI]([ITM]ITMREF,[ITM]ITMDES1,[ORD]WIPNUM)
  For [ORI]
       ...
  Next

 

Il est a noter une différence de comportement entre Oracle et SQL-server dans les boucles For, lorsqu'on créé des enregistrements vérifiant la clause where et dont la clé est supérieure à la clé courante : 

   sous Oracle, ces enregistrements ne seront jamais relus 
   sous SQL-server, ils seront lus à leur tour dans la boucle

Il est donc recommandé de ne pas utiliser de tels algorithmes, ou du moins, de se prémunir contre la relecture des enregistrements créés, par la clause "with stability". Attention, cette clause "With stability" ralentit l'exécution du fait de l' utilisation de tables temporaires pour chaque requête).

exemple sous SQL-serveur :

On admet la table XXX (CH1, CH2, FLG) avec 2 lignes :
'AAA', 'libellé 1', 0
'CCC', 'libellé 2', 1
avec la clé KEY qui porte sur le champ CH1
avec la clé KFL qui porte sur le champ FLG

For [XXX]KEY with stability
 If CHP1 ='AAA'
  CHP1 ='BBB'
  Rewrite [XXX]
 endif
Next

Avec un curseur stable, on lit 2 lignes : 'AAA, 'CCC'.
Avec un curseur non stable ( donc sans précision de la clause stability) , on lit 3 lignes  :
'AAA, 'BBB', 'CCC'.

For [XXX]KEY
  If CHP1 =
'CCC'
   CHP1 ='BBB'
   Rewrite [XXX]
 endif
Next

Stable ou Non stable, on lit 2 lignes : 'AAA, 'CCC' car la ligne ainsi modifiée n'est plus dans l'ordre normale de sélection.

 

Nouveautés de la version 130

Il est maintenant possible d'optimiser les lectures d'enregistrements lorsque la clé est composées de 2 éléments. On utilise l'une ou l'autre des 2 syntaxes qui s'appuient sur le principe du multi-requêtes  :

Le but est de simplifier les requêtes en évitant les "or" de la clause where de la requêtes.

Il est à noter que la syntaxe Forclé Fromclé_debToclé_fin   reste en mono requête et donc coûteuse en temps.

Exemple :
Local File ACCES[ACC]
For [ACC]CODACC From "AAA";"AAA" to"ZZZ";"ZZZ"
Next

génère la requête suivante (CODACC étant une clé à 2 partie) :

Select /*+ INDEX(ACC_ ACCES_CODACC) */ACC_.ROWID, ACC_.*
From X3.ACCES ACC_
Where ( ( ACC_.USR_0 = :1 And ACC_.CODACC_0 >= :2 )
Or ( ACC_.USR_0 > :1 ) )
And
( ( ACC_.USR_0 = :3 And ACC_.CODACC_0 <= :4 )
Or ( ACC_.USR_0 < :3 ) )
Order by ACC_.USR_0,ACC_.CODACC_0

 

Exemple optimisé :
Local File ACCES[ACC]
For [ACC]CODACC From "AAA";"AAA"
Next

génère la requête suivante  :

Select /*+ INDEX(ACC_ ACCES_CODACC) */ ACC_.ROWID, ACC_.*
From X3.ACCES ACC_
Where  ( ACC_.USR_0 = :1 And ACC_.CODACC_0 >= :2 )
Order by ACC_.USR_0,ACC_.CODACC_0

puis la requête suivante  :

Select /*+ INDEX(ACC_ ACCES_CODACC) */ ACC_.ROWID, ACC_.*
From X3.ACCES ACC_
Where  ( ACC_.USR_0 > :1 )
Order by ACC_.USR_0,ACC_.CODACC_0

 

Nouveautés de la version 140

Par défaut, le moteur Adonix  laisse la base déterminer la clé de parcours la plus appropriée à la lecture. La clause With Nohint devient l'option par défaut.

Sous SQL-Server, par défaut, le curseur est non stable. La clause With stability permet de le rendre stable.

 

Erreurs associées

Erreur

Description

ERCLAS (7):

Abréviation non trouvée.

ERRET (32)

Mauvaiseimbrication des bouclesFor (ForCLE(2) suivi deForCLE(1) par exemple) ou clause Where à l'intérieur d'une boucleFor.

FISLOCK(43)

Plus assezde verrous (avec With Lock).

 

Mots-clés associés

FORV - BREAK - WHILE - REPEAT - READ - LINK - LOCKWAIT - READLOCKCOLUMNS

CURRIND  -   CURRLEN - WHERE - HINT


SOMMAIRE

Adonix X3(r) L4G
Copyright (c) Adonix 1999 - All rights reserved