[ABAP] Tabellentypen mit Beispielen

Übersicht interne Tabellen: Link

Beispieltyp

TYPES: BEGIN OF ty_long,
         posnr   TYPE posnr,
         matnr   TYPE matnr,
         vbeln   TYPE vbeln,
         flag_ok TYPE boolean,
       END OF ty_long.

STANDARD TABLE

* unsortiert, kann mit SORT sortiert werden
* Zugriff über Index und Schlüssel

DATA: it_st TYPE STANDARD TABLE OF ty_long WITH DEFAULT KEY.

SORTED TABLE

* nach definiertem Schlüssel sortiert
* Zugriff über Index und Schlüssel
* wenn Zugriff über Schlüssel
* schnell, da binäre Suche  

* Primary Key: posnr
* Secondary Key: flag
DATA: it_so TYPE SORTED TABLE OF ty_long WITH UNIQUE KEY posnr WITH NON-UNIQUE SORTED KEY flag COMPONENTS flag_ok.

* Primary Key: table_line
DATA: it_sorted TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line.

HASHED TABLE

* Zugriff nur über eindeutigen Schlüssel, kein Index
* Zugriff nur über einen unique-Schlüssel -> jeder Schlüsselwert darf nur einmal vorkommen, sonst Exception
* schnell, wenn alle Schlüsselfelder einbezogen werden

* Primary Key: DEFAULT KEY
DATA: it_hadk TYPE HASHED TABLE OF ty_long WITH UNIQUE DEFAULT KEY.

* Primary Key: posnr
DATA: it_hauk TYPE HASHED TABLE OF ty_long WITH UNIQUE KEY posnr.

* Primary Key: DEFAULT KEY
* Secondary Key: flag 
DATA: it_hask TYPE HASHED TABLE OF ty_long WITH UNIQUE DEFAULT KEY WITH NON-UNIQUE SORTED KEY flag COMPONENTS flag_ok.

* Primary Key: posnr, matnr, vbeln
* Secondary Key: flag 
DATA: it_hauksk TYPE HASHED TABLE OF ty_long WITH UNIQUE KEY posnr matnr vbeln WITH NON-UNIQUE SORTED KEY flag COMPONENTS flag_ok.

[ABAP] Datensätze zwischen Tabellen mit unterschiedlichen Feldern und Datentypen kopieren

Beispiel 1 (APPEND CORRESPONDING)

* Typ für Tabelle mit kompletten Daten
TYPES: BEGIN OF ty_long,
         posnr   TYPE posnr,
         matnr   TYPE matnr,
         vbeln   TYPE vbeln,
         flag_ok TYPE boolean,
       END OF ty_long.

* Typ für Ausgabetabelle, Felder hier nur vom Datentyp string
TYPES: BEGIN OF ty_short,
         posnr TYPE string,
         matnr TYPE string,
         vbeln TYPE string,
       END OF ty_short.

DATA: it_long TYPE STANDARD TABLE OF ty_long WITH DEFAULT KEY.
DATA: it_short TYPE STANDARD TABLE OF ty_short WITH DEFAULT KEY.

* Beispieldaten
it_long = VALUE #( ( posnr = 1 matnr = '1111111111' vbeln = '3333333333' flag_ok = abap_true )
                   ( posnr = 2 matnr = '2222222222' vbeln = '4444444444' flag_ok = abap_false )
                   ( posnr = 3 matnr = '3333333333' vbeln = '5555555555' flag_ok = abap_true ) ).

* nur Datensätze kopieren, wo Flag gesetzt
LOOP AT it_long ASSIGNING FIELD-SYMBOL(<fs_l>) WHERE ( flag_ok = abap_true ).
* korrespondierende (namensgleiche) Felder des Datensatzes vom Typ ty_long an
* Tabelle mit Datensätzen vom Typ ty_short anhängen
  APPEND CORRESPONDING ty_short( <fs_l> ) TO it_short.
ENDLOOP.

* Testdaten ausgeben
LOOP AT it_short ASSIGNING FIELD-SYMBOL(<fs_s>).
  WRITE: / <fs_s>-posnr, <fs_s>-matnr, <fs_s>-vbeln.
ENDLOOP.

Beispiel 2 (CORRESPONDING, FILTER)

* Typ für Tabelle mit kompletten Daten
TYPES: BEGIN OF ty_long,
         posnr   TYPE posnr,
         matnr   TYPE matnr,
         vbeln   TYPE vbeln,
         flag_ok TYPE boolean,
       END OF ty_long.

* Typ für Ausgabetabelle, Felder hier nur vom Datentyp string
TYPES: BEGIN OF ty_short,
         posnr TYPE string,
         matnr TYPE string,
         vbeln TYPE string,
       END OF ty_short.

DATA: it_long TYPE SORTED TABLE OF ty_long WITH UNIQUE KEY posnr WITH NON-UNIQUE SORTED KEY flag COMPONENTS flag_ok.
DATA: it_short TYPE STANDARD TABLE OF ty_short WITH DEFAULT KEY.

* Beispieldaten
it_long = VALUE #( ( posnr = 1 matnr = '1111111111' vbeln = '3333333333' flag_ok = abap_true )
                   ( posnr = 2 matnr = '2222222222' vbeln = '4444444444' flag_ok = abap_false )
                   ( posnr = 3 matnr = '3333333333' vbeln = '5555555555' flag_ok = abap_true ) ).

* nur Datensätze kopieren, wo Flag gesetzt
* korrespondierende (namensgleiche) Felder des Datensatzes vom Typ ty_long in
* Tabelle mit Datensätzen vom Typ ty_short kopieren
it_short = CORRESPONDING #( FILTER #( it_long USING KEY flag WHERE flag_ok = abap_true ) ).

* Testdaten ausgeben
LOOP AT it_short ASSIGNING FIELD-SYMBOL(<fs_s>).
  WRITE: / <fs_s>-posnr, <fs_s>-matnr, <fs_s>-vbeln.
ENDLOOP.

[ABAP] Tabelleninhalt einer internen Tabelle anhand eines Kriteriums selektieren und kopieren (FILTER, VALUE, FOR, WHERE)

Variante 1 (VALUE, FOR, WHERE) – explizite Feldangabe

* Standardtabelle mit sortiertem Schlüssel carr_city definieren
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_for_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' selektieren
* und mittels VALUE und FOR kopieren
  it_for_spfli = VALUE #( FOR l IN it_spfli WHERE ( carrid = 'LH' )
                          ( mandt = l-mandt
                            carrid = l-carrid
                            connid = l-connid
                            countryfr = l-countryfr
                            cityfrom = l-cityfrom
                            airpfrom = l-airpfrom
                            countryto = l-countryto
                            cityto = l-cityto
                            airpto = l-airpto
                            fltime = l-fltime
                            deptime = l-deptime
                            arrtime = l-arrtime
                            distance = l-distance
                            distid = l-distid
                            fltype = l-fltype
                            period = l-period ) ).

  LOOP AT it_for_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

Variante 2 (VALUE, FOR, WHERE) – alle Felder mit Variable

* Standardtabelle mit sortiertem Schlüssel carr_city definieren
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_for_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' selektieren
* und mittels VALUE und FOR kopieren
* ( l ) -> komplette Zeile
  it_for_spfli = VALUE #( FOR l IN it_spfli WHERE ( carrid = 'LH' )
                          ( l ) ).

  LOOP AT it_for_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

Variante 3 (VALUE, FOR, WHERE) – alle Felder mit Feldsymbol

* Standardtabelle mit sortiertem Schlüssel carr_city definieren
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_for_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' selektieren
* und mittels VALUE und FOR kopieren
* ( l ) -> komplette Zeile
  it_for_spfli = VALUE #( FOR <fs> IN it_spfli WHERE ( carrid = 'LH' )
                          ( <fs> ) ).

  LOOP AT it_for_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

Variante 4 (FILTER, KEY, WHERE)

* Standardtabellem mit sortiertem Schlüssel
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH NON-UNIQUE SORTED KEY carr_city COMPONENTS carrid cityfrom.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_filter_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' mittels Filter selektieren und kopieren
* Daten sind anhand des Schlüssels vorsortiert
  it_filter_spfli = FILTER #( it_spfli USING KEY carr_city WHERE carrid = CONV #( 'LH' ) ).

  LOOP AT it_filter_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

[ABAP] Schleifenperformance durch Feldsymbole und binäre Suche verbessern

Variante 1 (langsam: keine Optimierung)

* Verkaufsbeleg: Kopfdaten
SELECT * FROM vbak INTO TABLE @DATA(it_vbak).
* Verkaufsbeleg: Positionsdaten
SELECT * FROM vbap INTO TABLE @DATA(it_vbap).

DATA(o_timer) = cl_abap_runtime=>create_hr_timer( ).
DATA(usec_start) = o_timer->get_runtime( ).

LOOP AT it_vbak ASSIGNING FIELD-SYMBOL(<k>).
  LOOP AT it_vbap ASSIGNING FIELD-SYMBOL(<p>) WHERE vbeln EQ <k>-vbeln.
    WRITE: / <p>-vbeln, <p>-matnr.
  ENDLOOP.
ENDLOOP.

DATA(usec_end) = o_timer->get_runtime( ).
DATA(usec) = CONV decfloat16( usec_end - usec_start ).
DATA(sec) = usec / 1000000.

WRITE: / 'Laufzeit:', sec, 's'.

Variante 2 (schnell: FIELD-SYMBOL, BINARY SEARCH)

* Verkaufsbeleg: Kopfdaten
SELECT * FROM vbak INTO TABLE @DATA(it_vbak).
* Verkaufsbeleg: Positionsdaten
SELECT * FROM vbap INTO TABLE @DATA(it_vbap).

* Tabelle muss aufsteigend sortiert sein, sonst stimmt der Rückgabeindex bei der binären Suche nicht
SORT: it_vbak BY vbeln.
SORT: it_vbap BY vbeln.

DATA(o_timer) = cl_abap_runtime=>create_hr_timer( ).
DATA(usec_start) = o_timer->get_runtime( ).

LOOP AT it_vbak ASSIGNING FIELD-SYMBOL(<k>).
* binäre Suche mit READ TABLE
* -> sollen stattdessen Table-Expressions verwendet werden, muss ein Sorted Key benutzt werden
  READ TABLE it_vbap TRANSPORTING NO FIELDS WITH KEY vbeln = <k>-vbeln BINARY SEARCH.
* gefundenen Index merken
  DATA(lv_index) = sy-tabix.

  IF sy-subrc = 0.
* Suche in der sortierten Tabelle ab Index lv_index
    LOOP AT it_vbap ASSIGNING FIELD-SYMBOL(<p>) FROM lv_index WHERE vbeln = <k>-vbeln.
      WRITE: / <p>-vbeln, <p>-matnr.
    ENDLOOP.
  ELSE.
    WRITE: / 'Fehler.'.
  ENDIF.
ENDLOOP.

DATA(usec_end) = o_timer->get_runtime( ).
DATA(usec) = CONV decfloat16( usec_end - usec_start ).
DATA(sec) = usec / 1000000.

WRITE: / 'Laufzeit:', sec, 's'.

Variante 3 (am schnellsten: FIELD-SYMBOLS, HASHED TABLES, Secondary Keys)

DATA: it_vbak TYPE HASHED TABLE OF vbak WITH UNIQUE KEY vbeln.
DATA: it_vbap TYPE HASHED TABLE OF vbap WITH UNIQUE KEY vbeln posnr                             " Primary Key
                                        WITH NON-UNIQUE SORTED KEY vbeln_sort COMPONENTS vbeln. " Secondary Key

* Verkaufsbeleg: Kopfdaten
SELECT * FROM vbak INTO TABLE it_vbak.
* Verkaufsbeleg: Positionsdaten
SELECT * FROM vbap INTO TABLE it_vbap.

DATA(o_timer) = cl_abap_runtime=>create_hr_timer( ).
DATA(usec_start) = o_timer->get_runtime( ).

LOOP AT it_vbak ASSIGNING FIELD-SYMBOL(<k>).
* Nested Loop über Secondary Key vbeln_sort
* BINARY SEARCH wird durch die Verwendung des Secondary Keys implizit ausgeführt
  LOOP AT it_vbap ASSIGNING FIELD-SYMBOL(<p>) USING KEY vbeln_sort WHERE vbeln = <k>-vbeln.
    WRITE: / <p>-vbeln, <p>-matnr.
  ENDLOOP.
ENDLOOP.

DATA(usec_end) = o_timer->get_runtime( ).
DATA(usec) = CONV decfloat16( usec_end - usec_start ).
DATA(sec) = usec / 1000000.

WRITE: / 'Laufzeit:', sec, 's'.

Links