ABAP DELETE pour les tables internes : supprimer des lignes

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

L’instruction DELETE pour les tables internes supprime une ou plusieurs lignes d’une table interne. Il existe differentes variantes : suppression par index, par cle, avec condition WHERE ou suppression des doublons.

Syntaxe

1. Supprimer une ligne par index

DELETE <table_interne> INDEX <index>.

2. Supprimer une ligne par cle

DELETE TABLE <table_interne> FROM <zone_travail>.
DELETE TABLE <table_interne> WITH TABLE KEY <cle> = <valeur>.

3. Supprimer plusieurs lignes avec WHERE

DELETE <table_interne> WHERE <condition>.

4. Supprimer la ligne dans le LOOP courant

LOOP AT <table_interne> ...
DELETE <table_interne>. " Supprime la ligne courante
ENDLOOP.

5. Supprimer les doublons

DELETE ADJACENT DUPLICATES FROM <table_interne>
[COMPARING <champs> | ALL FIELDS]
[USING KEY <cle>].

Champs systeme

Apres DELETE :

  • sy-subrc :

    • 0 : Au moins une ligne supprimee
    • 4 : Aucune ligne correspondante trouvee
  • sy-tabix : Avec DELETE ... INDEX inchange ; sinon indefini

Exemples

1. Supprimer une ligne par index

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernard` ) ( `Clara` ) ( `David` ) ).
" Supprimer la deuxieme ligne
DELETE lt_names INDEX 2.
" Resultat : Anna, Clara, David
LOOP AT lt_names INTO DATA(lv_name).
WRITE: / lv_name.
ENDLOOP.

2. Supprimer la premiere et la derniere ligne

DATA: lt_data TYPE TABLE OF i.
lt_data = VALUE #( ( 10 ) ( 20 ) ( 30 ) ( 40 ) ( 50 ) ).
" Supprimer la premiere ligne
DELETE lt_data INDEX 1.
" Supprimer la derniere ligne
DELETE lt_data INDEX lines( lt_data ).
" Resultat : 20, 30, 40

3. Supprimer une ligne par cle (FROM)

TYPES: BEGIN OF ty_customer,
id TYPE i,
name TYPE string,
END OF ty_customer.
DATA: lt_customers TYPE HASHED TABLE OF ty_customer WITH UNIQUE KEY id,
ls_customer TYPE ty_customer.
lt_customers = VALUE #(
( id = 1 name = 'Muller' )
( id = 2 name = 'Schmidt' )
( id = 3 name = 'Weber' )
).
" Supprimer le client avec ID 2
ls_customer-id = 2.
DELETE TABLE lt_customers FROM ls_customer.
IF sy-subrc = 0.
WRITE: / 'Client supprime.'.
ELSE.
WRITE: / 'Client non trouve.'.
ENDIF.

4. Supprimer une ligne par cle (WITH TABLE KEY)

" Acces direct par cle
DELETE TABLE lt_customers WITH TABLE KEY id = 3.
IF sy-subrc = 0.
WRITE: / 'Client 3 supprime.'.
ENDIF.

5. Supprimer 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 TABLE OF ty_order.
lt_orders = VALUE #(
( order_id = 1 status = 'OPEN' amount = '100.00' )
( order_id = 2 status = 'CANCELLED' amount = '200.00' )
( order_id = 3 status = 'OPEN' amount = '150.00' )
( order_id = 4 status = 'CANCELLED' amount = '300.00' )
( order_id = 5 status = 'COMPLETED' amount = '250.00' )
).
" Supprimer toutes les commandes annulees
DELETE lt_orders WHERE status = 'CANCELLED'.
WRITE: / 'Lignes supprimees:', sy-dbcnt.
WRITE: / 'Lignes restantes:', lines( lt_orders ).
" Resultat : order_id 1, 3, 5 restent

6. Condition WHERE complexe

" Combiner plusieurs conditions
DELETE lt_orders WHERE status = 'OPEN"
AND amount < 120.
" Avec OR
DELETE lt_orders WHERE status = 'CANCELLED"
OR amount = 0.
" Avec IN
DATA: lt_status TYPE RANGE OF string.
lt_status = VALUE #( ( sign = 'I' option = 'EQ' low = 'CANCELLED' )
( sign = 'I' option = 'EQ' low = 'REJECTED' ) ).
DELETE lt_orders WHERE status IN lt_status.

7. Supprimer une ligne dans un LOOP

" ATTENTION : DELETE dans un LOOP est autorise, mais prudence avec les Field-Symbols !
DATA: lt_numbers TYPE TABLE OF i.
lt_numbers = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ( 6 ) ).
" Supprimer tous les nombres pairs
LOOP AT lt_numbers INTO DATA(lv_num).
IF lv_num MOD 2 = 0.
DELETE lt_numbers.
ENDIF.
ENDLOOP.
" Resultat : 1, 3, 5

8. DELETE dans un LOOP avec ASSIGNING (Attention !)

" Avec ASSIGNING, DELETE est problematique !
LOOP AT lt_numbers ASSIGNING FIELD-SYMBOL(<fs_num>).
IF <fs_num> MOD 2 = 0.
DELETE lt_numbers.
" ATTENTION : <fs_num> pointe maintenant vers des donnees invalides !
" D'autres acces a <fs_num> peuvent causer des erreurs.
ENDIF.
ENDLOOP.
" MIEUX : Travailler avec INTO ou utiliser WHERE
DELETE lt_numbers WHERE table_line MOD 2 = 0.

9. DELETE ADJACENT DUPLICATES - Supprimer les doublons

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #(
( `Anna` ) ( `Anna` ) ( `Bernard` ) ( `Clara` )
( `Clara` ) ( `Clara` ) ( `David` )
).
" Supprimer les doublons consecutifs
DELETE ADJACENT DUPLICATES FROM lt_names.
" Resultat : Anna, Bernard, Clara, David
LOOP AT lt_names INTO DATA(lv_name).
WRITE: / lv_name.
ENDLOOP.

10. DELETE ADJACENT DUPLICATES apres SORT

TYPES: BEGIN OF ty_product,
category TYPE string,
name TYPE string,
price TYPE p DECIMALS 2,
END OF ty_product.
DATA: lt_products TYPE TABLE OF ty_product.
lt_products = VALUE #(
( category = 'A' name = 'Prod1' price = 10 )
( category = 'B' name = 'Prod2' price = 20 )
( category = 'A' name = 'Prod3' price = 15 )
( category = 'A' name = 'Prod1' price = 10 ) " Doublon
( category = 'B' name = 'Prod2' price = 25 ) " Doublon partiel
).
" IMPORTANT : Trier d'abord !
SORT lt_products BY category name.
" Supprimer les doublons par category et name
DELETE ADJACENT DUPLICATES FROM lt_products
COMPARING category name.
" Resultat : Seules les combinaisons category/name uniques

11. COMPARING ALL FIELDS

" Ne supprimer que les doublons exacts (tous les champs identiques)
SORT lt_products BY category name price.
DELETE ADJACENT DUPLICATES FROM lt_products
COMPARING ALL FIELDS.

12. USING KEY pour cle secondaire

DATA: lt_data TYPE SORTED TABLE OF ty_product
WITH UNIQUE KEY category name
WITH NON-UNIQUE SORTED KEY by_price COMPONENTS price.
" Supprimer les doublons par prix
DELETE ADJACENT DUPLICATES FROM lt_data
USING KEY by_price.

13. Supprimer une plage (FROM … TO)

DATA: lt_nums TYPE TABLE OF i.
lt_nums = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ( 6 ) ( 7 ) ( 8 ) ).
" Supprimer les lignes 3 a 6
DELETE lt_nums FROM 3 TO 6.
" Resultat : 1, 2, 7, 8

14. DELETE pour differents types de tables

Type de tableINDEXFROM waWITH TABLE KEYWHERE
STANDARDOuiOui (lineaire)OuiOui
SORTEDOuiOui (binaire)OuiOui
HASHEDNonOui (hash)OuiOui
" STANDARD TABLE : Toutes les variantes possibles
DATA: lt_standard TYPE STANDARD TABLE OF ty_customer.
DELETE lt_standard INDEX 1.
DELETE TABLE lt_standard FROM ls_customer.
DELETE lt_standard WHERE name = 'Test'.
" HASHED TABLE : Pas d'INDEX !
DATA: lt_hashed TYPE HASHED TABLE OF ty_customer WITH UNIQUE KEY id.
" DELETE lt_hashed INDEX 1. " ERREUR !
DELETE TABLE lt_hashed WITH TABLE KEY id = 1. " OK
DELETE lt_hashed WHERE name = 'Test'. " OK

Comparaison : DELETE vs. CLEAR vs. FREE

InstructionEffet
DELETE itab ...Supprime certaines lignes
CLEAR itabSupprime toutes les lignes, conserve la memoire
FREE itabSupprime toutes les lignes, libere la memoire
" Supprimer certaines lignes
DELETE lt_data WHERE status = 'X'.
" Supprimer toutes les lignes (conserver la memoire)
CLEAR lt_data.
" Supprimer toutes les lignes et liberer la memoire
FREE lt_data.

Conseils de performance

  1. WHERE au lieu de LOOP avec DELETE :

    " LENT
    LOOP AT lt_data INTO ls_data.
    IF ls_data-status = 'X'.
    DELETE lt_data.
    ENDIF.
    ENDLOOP.
    " PLUS RAPIDE
    DELETE lt_data WHERE status = 'X'.
  2. SORT avant ADJACENT DUPLICATES : DELETE ADJACENT DUPLICATES ne reconnait que les doublons consecutifs. Triez d’abord !

  3. Suppression par index depuis la fin :

    " Lors de la suppression de plusieurs lignes par index : de la fin vers le debut
    DO 3 TIMES.
    DELETE lt_data INDEX lines( lt_data ).
    ENDDO.
  4. Suppression en masse efficace : Pour supprimer de nombreuses lignes, DELETE ... WHERE est plus efficace que des suppressions individuelles.

Remarques importantes / Bonnes pratiques

  • Verifiez sy-subrc apres DELETE ... INDEX ou DELETE TABLE.
  • DELETE ... WHERE definit sy-subrc = 0 meme si aucune ligne n’a ete supprimee (mais sy-dbcnt = 0).
  • Triez avant DELETE ADJACENT DUPLICATES.
  • Attention lors de la suppression dans LOOP AT avec ASSIGNING - le Field-Symbol devient invalide !
  • Avec HASHED TABLE, DELETE ... INDEX n’est pas possible.
  • Pour les tables de base de donnees, utilisez DELETE FROM dbtab.
  • DELETE ADJACENT DUPLICATES ne supprime que les doublons adjacents.
  • Utilisez SORT en combinaison avec DELETE ADJACENT DUPLICATES pour des listes uniques.