Structuren, interne tabellen & field-symbols
De belangrijkste datastructuren in ABAP: structuren, de drie soorten interne tabellen met hun keys, alle bewerkings-statements, en dynamische toegang via field-symbols en data-referenties.
01Structuren
Een structuur is een record: één "regel" met vooraf vastgelegde velden. De bouwsteen voor vrijwel alle data-uitwisseling in SAP.
TYPES: BEGIN OF ty_order,
vbeln TYPE vbeln_va, " ordernummer
erdat TYPE erdat, " aanmaakdatum
netwr TYPE netwr_ak, " nettowaarde
END OF ty_order.
DATA ls_order TYPE ty_order.
ls_order-vbeln = '0000012345'. " veldtoegang met een koppelteken
ls_order = VALUE #( vbeln = '0000012345' erdat = sy-datum ). " modern, in één keer
- Veldtoegang gaat met een koppelteken:
ls_order-vbeln. (Bij objecten is het->, bij statische class-toegang=>— zie classes.) - Structuren kunnen genest zijn (een veld dat zelf een structuur of tabel is):
ls_kop-adres-plaats. MOVE-CORRESPONDING ls_a TO ls_b.kopieert alle velden met gelijke naam — ook als de structuren verder verschillen. Modern equivalent:ls_b = CORRESPONDING #( ls_a ).CLEAR ls_order.maakt alle velden initieel.
Bekende voorgedefinieerde structuren: databasetabel-regels (DATA ls_mara TYPE mara.), BAPI-structuren (BAPIRET2, zie foutafhandeling) en de systeemstructuur sy.
02Interne tabellen: de drie soorten
Een interne tabel is een lijst van structuren in het geheugen — het werkpaard van ABAP. De soort bepaalt hoe regels worden opgeslagen en hoe snel je ze terugvindt.
DATA: lt_std TYPE STANDARD TABLE OF ty_order WITH EMPTY KEY,
lt_sorted TYPE SORTED TABLE OF ty_order
WITH UNIQUE KEY vbeln,
lt_hashed TYPE HASHED TABLE OF ty_order
WITH UNIQUE KEY vbeln.
| Soort | Opslag | Zoeken op key | Wanneer |
|---|---|---|---|
STANDARD | Volgorde van toevoegen (index-tabel) | Lineair — O(n), tenzij BINARY SEARCH na SORT | Standaardkeuze; sequentieel verwerken, APPEND-en |
SORTED | Altijd gesorteerd op de key (index-tabel) | Binair — O(log n), automatisch | Vaak zoeken op (deel van) de key én index-toegang nodig |
HASHED | Hash-tabel, geen index/volgorde | O(1), alleen op de vólledige unieke key | Grote tabellen met puur key-lookups (bijv. buffers) |
- Key:
WITH UNIQUE KEY(dubbele keys geven een fout of dump) ofWITH NON-UNIQUE KEY.WITH DEFAULT KEY= alle tekstvelden (bijna nooit wat je wilt);WITH EMPTY KEY= expliciet geen key (netjes voor standard tables). - Secundaire keys: extra zoekingangen op een bestaande tabel:
WITH NON-UNIQUE SORTED KEY per_mat COMPONENTS matnr.Gebruiken metREAD ... USING KEY per_mat. - Header lines — in zéér oude code (
OCCURS 0 WITH HEADER LINE) heeft de tabel een gelijknamige werkstructuur. Verboden in nieuwe code; herken je aanlt_tab[](de tabel zelf) vs.lt_tab(de headerregel).
03Interne tabellen bewerken
Alle statements om regels toe te voegen, te vinden, te wijzigen en te verwijderen.
Toevoegen
APPEND ls_order TO lt_orders. " achteraan (alleen standard)
APPEND INITIAL LINE TO lt_orders ASSIGNING FIELD-SYMBOL(<ls_new>).
INSERT ls_order INTO TABLE lt_sorted. " op de juiste plek (sorted/hashed)
INSERT ls_order INTO lt_orders INDEX 1. " op positie (index-tabellen)
APPEND LINES OF lt_extra TO lt_orders. " tabel aan tabel plakken
Bij INSERT INTO TABLE op een unieke key: bestaat de key al, dan wordt níét ingevoegd en is sy-subrc = 4.
Lezen: READ TABLE en table expressions
READ TABLE lt_orders INTO ls_order WITH KEY vbeln = '0000012345'.
IF sy-subrc = 0. " gevonden
ENDIF.
READ TABLE lt_orders ASSIGNING FIELD-SYMBOL(<ls_order>) INDEX 1.
READ TABLE lt_orders TRANSPORTING NO FIELDS WITH KEY vbeln = lv_vbeln. " alleen bestaanscheck
" Moderne table expression — dumpt (CX_SY_ITAB_LINE_NOT_FOUND) als niet gevonden:
ls_order = lt_orders[ vbeln = '0000012345' ].
ls_order = VALUE #( lt_orders[ vbeln = lv_vbeln ] OPTIONAL ). " leeg i.p.v. dump
IF line_exists( lt_orders[ vbeln = lv_vbeln ] ). " nette bestaanscheck
Loopen
LOOP AT lt_orders INTO ls_order WHERE netwr > 1000.
" ls_order is een KOPIE — wijzigingen raken de tabel niet
ENDLOOP.
LOOP AT lt_orders ASSIGNING FIELD-SYMBOL(<ls_order>).
<ls_order>-netwr = <ls_order>-netwr * '1.21'. " wijzigt de tabel direct
ENDLOOP.
LOOP AT lt_orders INTO ls_order FROM 1 TO 100. " indexbereik
ENDLOOP.
Binnen een loop is sy-tabix het huidige regelnummer. Groepsverwerking ("control break") kan klassiek met AT NEW veld ... ENDAT (vereist gesorteerde tabel) of modern met LOOP AT ... GROUP BY.
Wijzigen & verwijderen
MODIFY lt_orders FROM ls_order INDEX sy-tabix. " regel vervangen
MODIFY lt_orders FROM ls_default
TRANSPORTING status WHERE status IS INITIAL. " massa-update van één veld
DELETE lt_orders WHERE netwr = 0.
DELETE lt_orders INDEX 3.
DELETE ADJACENT DUPLICATES FROM lt_orders COMPARING vbeln. " na SORT!
Sorteren, optellen, overig
SORT lt_orders BY erdat DESCENDING vbeln ASCENDING.
SORT lt_orders BY netwr STABLE. " behoudt volgorde bij gelijke waarden
COLLECT ls_som INTO lt_sommen. " telt numerieke velden op bij gelijke key
DESCRIBE TABLE lt_orders LINES DATA(lv_aantal). " of: lv_aantal = lines( lt_orders ).
CLEAR lt_orders. " leegmaken (FREE geeft ook geheugen terug)
SORT zonder BY sorteert op de (default) key; bij WITH EMPTY KEY doet hij niets zinvols. En DELETE ADJACENT DUPLICATES werkt alleen op aangrenzende regels — altijd eerst sorteren op dezelfde velden.04Field-symbols
Een field-symbol is geen variabele maar een verwijzing ("alias") naar een bestaand data-object. Herkenbaar aan de punthaken.
FIELD-SYMBOLS <fs_order> TYPE ty_order.
ASSIGN ls_order TO <fs_order>.
<fs_order>-netwr = 100. " wijzigt ls_order zelf
" Inline (gangbaarst): declaratie op de plek van gebruik
LOOP AT lt_orders ASSIGNING FIELD-SYMBOL(<ls_o>).
...
ENDLOOP.
- Waarom: geen kopieerkosten (sneller bij brede regels), en wijzigingen werken direct door in de tabel — vandaar het vaste duo
LOOP ... ASSIGNING. IF <fs> IS ASSIGNED.— check of het field-symbol ergens naar wijst;UNASSIGN <fs>.maakt de koppeling los.- Na
ASSIGNmet een dynamische component altijdsy-subrcchecken (zie hieronder).
Dynamische toegang
ASSIGN COMPONENT 'NETWR' OF STRUCTURE ls_order TO FIELD-SYMBOL(<fs_veld>).
IF sy-subrc = 0.
WRITE <fs_veld>.
ENDIF.
ASSIGN ('(SAPLMEPO)EKKO') TO <fs_ekko>. " berucht: veld in een ANDER programma
" — komt voor in user exits, zie enhancements
De laatste vorm zie je in user exits: daarmee "gluur" je in de globale data van het aanroepende standaardprogramma. Krachtig, maar fragiel — documenteer het altijd.
05Data-referenties
Naast field-symbols kent ABAP echte referenties (pointers) naar data-objecten — nodig voor volledig dynamische structuren.
DATA lr_data TYPE REF TO data. " generieke data-referentie
CREATE DATA lr_data TYPE ty_order. " of dynamisch: TYPE (lv_typenaam)
ASSIGN lr_data->* TO FIELD-SYMBOL(<fs_order>). " dereferentie
DATA(lr_bestaand) = REF #( ls_order ). " referentie naar bestaand object
Typisch gebruik: generieke frameworks (bijv. een ALV die elke tabel aankan), RTTS (Run Time Type Services, classes CL_ABAP_TYPEDESCR en familie) en het dynamisch opbouwen van tabellen waarvan het type pas tijdens runtime bekend is.