Instruction ABAP MODIFY : Modifier des lignes dans les tables internes

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

L’instruction MODIFY est utilisee en ABAP pour modifier des lignes existantes dans les tables internes. Elle peut mettre a jour une seule ligne (par index ou cle) ou plusieurs lignes simultanement (avec une condition WHERE). Si la ligne n’existe pas, MODIFY peut aussi l’inserer selon la variante.

Syntaxe

Il existe plusieurs variantes de l’instruction MODIFY :

1. Modifier une ligne par index

MODIFY <table_interne> FROM <zone_de_travail> INDEX <index>
[TRANSPORTING <composant1> <composant2> ...].

2. Modifier ou inserer une ligne par cle de table

MODIFY TABLE <table_interne> FROM <zone_de_travail>
[TRANSPORTING <composant1> <composant2> ...].

3. Modifier plusieurs lignes avec condition WHERE

MODIFY <table_interne> FROM <zone_de_travail>
TRANSPORTING <composant1> [<composant2> ...]
WHERE <condition>.

4. Modifier la ligne courante dans un LOOP

LOOP AT <table_interne> INTO <zone_de_travail>.
" modifier <zone_de_travail>
MODIFY <table_interne> FROM <zone_de_travail>.
ENDLOOP.

Composants

  • <table_interne> : La table dont les lignes doivent etre modifiees.
  • <zone_de_travail> : Une structure avec les nouvelles valeurs. Doit etre compatible avec le type de ligne de la table.
  • INDEX <index> : La position de la ligne a modifier (uniquement pour les tables standard et triees).
  • TABLE : Indique la variante avec recherche par cle. La ligne est recherchee par la cle primaire.
  • TRANSPORTING <composants> : Limite la modification aux composants specifies. Les autres champs restent inchanges.
  • WHERE <condition> : Modifie toutes les lignes qui satisfont la condition.

Champs systeme

Apres un MODIFY, les champs systeme suivants sont definis :

  • sy-subrc :

    • 0 : Ligne(s) modifiee(s) avec succes (ou inseree avec MODIFY TABLE).
    • 4 : Aucune ligne correspondante trouvee (avec INDEX ou TABLE).
  • sy-tabix : Contient l’index de la ligne modifiee (pour les operations sur une seule ligne dans les tables indexees).

Fonctionnement par variante

MODIFY … INDEX

Modifie la ligne a la position d’index specifiee. Le contenu entier de la zone de travail est copie dans la ligne (sauf avec TRANSPORTING).

" Remplacer completement la ligne 3
MODIFY lt_data FROM ls_new_data INDEX 3.
" Modifier seulement certains champs de la ligne 3
MODIFY lt_data FROM ls_new_data INDEX 3 TRANSPORTING field1 field2.

MODIFY TABLE

Recherche la ligne par la cle primaire dans la zone de travail :

  • Trouvee : La ligne est mise a jour.
  • Non trouvee : La ligne est inseree (comme INSERT).
" Recherche par cle et modifie ou insere
MODIFY TABLE lt_customers FROM ls_customer.

MODIFY … WHERE

Modifie toutes les lignes qui satisfont la condition WHERE. TRANSPORTING est obligatoire ici.

" Modifier toutes les lignes avec status = 'OLD"
MODIFY lt_orders FROM ls_update
TRANSPORTING status
WHERE status = 'OLD'.

MODIFY dans LOOP (sans INDEX)

Dans un LOOP AT ... INTO, MODIFY peut etre utilise sans INDEX - il modifie alors automatiquement la ligne courante.

LOOP AT lt_data INTO ls_data.
ls_data-field = 'Nouvelle valeur'.
MODIFY lt_data FROM ls_data.
ENDLOOP.

Mieux : Utilisez ASSIGNING dans le loop pour des modifications directes sans MODIFY.

Exemples

1. Modifier une ligne par index

TYPES: BEGIN OF ty_product,
id TYPE i,
name TYPE string,
price TYPE p DECIMALS 2,
END OF ty_product.
DATA: lt_products TYPE STANDARD TABLE OF ty_product WITH EMPTY KEY,
ls_product TYPE ty_product.
" Remplir la table
lt_products = VALUE #(
( id = 1 name = 'Ordinateur' price = '999.00' )
( id = 2 name = 'Souris' price = '29.99' )
( id = 3 name = 'Clavier' price = '79.00' )
).
" Remplacer completement la ligne 2
ls_product = VALUE #( id = 2 name = 'Souris Gaming' price = '59.99' ).
MODIFY lt_products FROM ls_product INDEX 2.
IF sy-subrc = 0.
WRITE: / 'Ligne 2 modifiee.'.
ENDIF.

2. Modifier seulement certains champs (TRANSPORTING)

" Modifier seulement le prix de la ligne 1
ls_product-price = '899.00'.
MODIFY lt_products FROM ls_product INDEX 1 TRANSPORTING price.
" Le nom et l'ID restent inchanges
" Voir aussi : /read-table-statement/
READ TABLE lt_products INTO ls_product INDEX 1.
WRITE: / 'Produit:', ls_product-name, 'Prix:', ls_product-price.
" Sortie : Ordinateur 899.00

3. MODIFY TABLE (base sur la cle)

TYPES: BEGIN OF ty_customer,
id TYPE i,
name TYPE string,
city TYPE string,
END OF ty_customer.
DATA: lt_customers TYPE HASHED TABLE OF ty_customer WITH UNIQUE KEY id,
ls_customer TYPE ty_customer.
" Remplir la table
lt_customers = VALUE #(
( id = 1 name = 'Dupont SARL' city = 'Paris' )
( id = 2 name = 'Martin SA' city = 'Lyon' )
).
" Modifier un client existant (ID 1 existe)
ls_customer = VALUE #( id = 1 name = 'Dupont & Co SARL' city = 'Paris' ).
MODIFY TABLE lt_customers FROM ls_customer.
IF sy-subrc = 0.
WRITE: / 'Client 1 modifie.'.
ENDIF.
" Inserer un nouveau client (ID 3 n'existe pas)
ls_customer = VALUE #( id = 3 name = 'Weber SAS' city = 'Marseille' ).
MODIFY TABLE lt_customers FROM ls_customer.
WRITE: / 'Nombre de clients:', lines( lt_customers ). " Sortie : 3

4. Modifier plusieurs lignes avec WHERE

TYPES: BEGIN OF ty_order,
order_id TYPE i,
status TYPE string,
amount TYPE p DECIMALS 2,
END OF ty_order.
DATA: lt_orders TYPE STANDARD TABLE OF ty_order WITH EMPTY KEY,
ls_update TYPE ty_order.
lt_orders = VALUE #(
( order_id = 1 status = 'NOUVEAU' amount = '100.00' )
( order_id = 2 status = 'NOUVEAU' amount = '250.00' )
( order_id = 3 status = 'OUVERT' amount = '180.00' )
( order_id = 4 status = 'NOUVEAU' amount = '320.00' )
).
" Passer toutes les commandes avec statut 'NOUVEAU' a 'EN_TRAITEMENT"
ls_update-status = 'EN_TRAITEMENT'.
MODIFY lt_orders FROM ls_update
TRANSPORTING status
WHERE status = 'NOUVEAU'.
" Resultat : 3 lignes modifiees (order_id 1, 2, 4)
LOOP AT lt_orders INTO DATA(ls_order).
WRITE: / ls_order-order_id, ls_order-status.
ENDLOOP.

5. MODIFY dans LOOP avec INTO

DATA: ls_prod TYPE ty_product.
" Augmenter tous les prix de 10%
LOOP AT lt_products INTO ls_prod.
ls_prod-price = ls_prod-price * '1.1'.
MODIFY lt_products FROM ls_prod.
ENDLOOP.

6. Meilleure alternative : LOOP avec ASSIGNING

FIELD-SYMBOLS: <fs_prod> TYPE ty_product.
" Augmenter tous les prix de 10% - sans MODIFY
LOOP AT lt_products ASSIGNING <fs_prod>.
<fs_prod>-price = <fs_prod>-price * '1.1'.
ENDLOOP.
" Les modifications sont immediatement effectives, pas de MODIFY necessaire !

7. MODIFY TABLE avec TRANSPORTING

" Modifier seulement la ville d'un client (recherche par cle)
ls_customer-id = 2. " Cle pour la recherche
ls_customer-city = 'Nice'. " Nouvelle valeur
MODIFY TABLE lt_customers FROM ls_customer TRANSPORTING city.
IF sy-subrc = 0.
WRITE: / 'Ville du client 2 modifiee.'.
ENDIF.

Comportement par type de table

Type de tableINDEXTABLEWHERE
STANDARD TABLEOuiOui (recherche lineaire)Oui
SORTED TABLEOuiOui (recherche binaire)Oui
HASHED TABLENonOui (recherche par hash)Oui

Important pour les tables triees : Si vous modifiez les champs cle, cela peut violer l’ordre de tri et provoquer une erreur d’execution !

" Dangereux avec SORTED TABLE avec KEY id :
ls_customer-id = 999. " Modifier le champ cle
MODIFY TABLE lt_sorted_customers FROM ls_customer. " Peut provoquer un dump !

Distinction avec d’autres instructions

MODIFY vs. ASSIGNING dans LOOP

AspectMODIFY dans LOOPASSIGNING
SyntaxePlus de codePlus compact
PerformancePlus lent (copie)Plus rapide (acces direct)
UtilisationCode legacyRecommande
" Avec MODIFY (obsolete)
LOOP AT lt_data INTO ls_data.
ls_data-field = 'X'.
MODIFY lt_data FROM ls_data.
ENDLOOP.
" Avec ASSIGNING (recommande)
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-field = 'X'.
ENDLOOP.

MODIFY vs. INSERT et APPEND

  • MODIFY TABLE : Modifie une ligne existante OU insere une nouvelle (Upsert).
  • INSERT : Insere seulement, echoue si la cle existe.
  • APPEND : Ajoute toujours a la fin d’une table standard.

MODIFY vs. UPDATE (Base de donnees)

  • MODIFY : Pour les tables internes (en memoire).
  • UPDATE : Pour les tables de base de donnees (donnees persistantes).

Pour rechercher une ligne avant de la modifier, voir READ TABLE.

Conseils de performance

  1. ASSIGNING au lieu de MODIFY dans LOOP : Evitez LOOP ... INTO suivi de MODIFY. Utilisez ASSIGNING pour un acces direct en ecriture.

  2. TRANSPORTING pour les grandes structures : Si seulement quelques champs sont modifies, limitez les donnees copiees avec TRANSPORTING.

  3. WHERE pour les modifications de masse : MODIFY ... WHERE est plus efficace qu’une boucle manuelle avec modifications individuelles.

  4. Ne pas modifier les champs cle : Pour les tables triees et hash, les champs cle ne devraient pas etre modifies. Plutot : supprimer la ligne et en inserer une nouvelle (voir APPEND ou INSERT).

Remarques importantes / Bonnes pratiques

  • Verifiez sy-subrc apres MODIFY avec INDEX ou TABLE pour vous assurer que la ligne a ete trouvee.
  • Preferez ASSIGNING dans LOOP AT pour les modifications directes - c’est plus performant et plus elegant que MODIFY.
  • Utilisez TRANSPORTING quand seuls certains champs doivent etre modifies.
  • MODIFY TABLE est un “Upsert” - il insere si la ligne n’existe pas.
  • Ne modifiez jamais les champs cle directement pour les tables triees ou hash.
  • Pour MODIFY ... WHERE, TRANSPORTING est obligatoire.
  • Cette instruction MODIFY est pour les tables internes. Pour les tables de base de donnees, voir INSERT, UPDATE, DELETE.