Ansicht
Dokumentation

ABAPSHEETS_INTERNAL_TABLES - SHEETS INTERNAL TABLES

ABAPSHEETS_INTERNAL_TABLES - SHEETS INTERNAL TABLES

ROGBILLS - Synchronize billing plans   TXBHW - Original Tax Base Amount in Local Currency  
Diese Dokumentation steht unter dem Copyright der SAP AG.
SAP E-Book

Arbeiten mit internen Tabellen

In diesem Spickzettel sehen Sie schnelle Informationen über das Arbeiten mit internen Tabellen in ABAP. Darüber hinaus bietet er Ihnen eine nützliche Referenzsammlung von Syntax- und Quelltextstücken. Weitere Informationen finden Sie im entsprechenden Abschnitt der ABAP-Schlüsselwortdokumentation.

Interne Tabellen ...

  • sind Datentypen in ABAP.
  • können als Gruppierungen von Tabellenzeilen betrachtet werden.
  • nehmen überlicherweise Daten aus einer festen Struktur auf und speichern diese im ABAP-Arbeitsspeicher, d.h. die Daten werden zeilenweise in den Speicher gesichert und jede Zeile hat die gleiche Struktur.
  • sind in folgenden Fällen relevant ...
  • .... Sie wollen eine Datenmenge mit einer festen Struktur innerhalb eines Programms verarbeiten.

  • ....wenn mehrere verwandte Datensätze vom gleichen Datentyp in einer einzelnen Variablen verwaltet werden.

  • ... wenn Daten aus einer Datenbanktabelle innerhalb eines Programms gespeichert und formatiert werden. Da sie im Speicher vorhanden sind ist ein Datenzugriff über interne Tabellen wesentlich schneller als der Zugriff auf Daten in Datenbanktabellen.

  • werden innerhalb des ABAP-Quelltexts deklariert.
  • sind dynamische Datenobjekte, d.h. sie können unterschiedlich verarbeitet werden.
  • Tabellenzeilen können beispielsweise eingefügt, gelöscht oder aktualisiert werden.

  • Der Zugriff auf die Tabellen kann unterschiedlich erfolgen, beispielsweise über Index oder Schlüssel, und sie können in einer Schleife sequentiell verarbeitet werden.

  • sind nur temporär im Speicher vorhanden; nach Beenden des Programms steht der Inhalt einer internen Tabelle nicht mehr zur Verfügung.
  • sind einfach zu verwalten, da das Laufzeit automatisch für die Speicherverwaltung zuständig ist, d.h. es berechnet bei der Deklaration der internen Tabelle eine passende initiale Speicherbelegung; wenn die Tabelle um Daten erweitert wird, wächst sie automatisch; wenn die Tabelle geleert wird, wird der überflüssige Speicher automatisch freigegeben.
  • werden durch ihre Zeilentypen, Tabellenarten und Schlüsselattribute ausgeprägt.

Weitere Informationen: Interne Tabellen

Interne Tabellen deklarieren

Das relevant syntaktische Element ist TABLE OF mit TYPES (Deklaration eines internen Tabellentyps) und DATA (Anlegen der internen Tabelle) und den Zusätzen TYPE oder LIKE. Weitere Informationen und Beispiele finden Sie im Abschnitt Interne Tabellen anlegen weiter unten.

Beispiele

TYPES itab_type1 TYPE STANDARD TABLE OF data_type ...
TYPES itab_type2 LIKE SORTED   TABLE OF data_object ...
DATA  itab1      TYPE          TABLE OF data_type ...
DATA  itab2      TYPE HASHED   TABLE OF data_type ...
DATA  itab3      TYPE                   table_type ...
DATA  itab4      LIKE                   table ...

Wenn keine Tabellenart (siehe unten) angegeben wird (...TYPE TABLE OF...), wird ...TYPE STANDARD TABLE OF... automatisch verwendet.

Merkmale

Jede interne Tabelle wird durch drei Aspekte ausgeprägt. Weitere Details: Interne Tabellen - Übersicht

Zeilentyp

  • Definiert den Aufbau jeder Zeile der internen Tabelle, d.h. hiermit werden die Spalten der Tabelle beschrieben.
  • Der Zeilentyp darf jeder ABAP-Datentyp sein, beispielsweise eine Struktur oder eine interne Tabelle.
  • In den meisten Fällen ist der Zeilentyp eine Struktur und jede Zeile in der internen Tabelle besitzt dann eine Spalte mit dem Namen und Typ der passenden Strukturkomponente.
  • In einem einfachen Fall besteht die Zeile aus einer flachen Struktur mit elementären Datenobjekten, sie kann aber auch eine tiefe Struktur mit Komponenten, die selbst Strukturen oder interne Tabellen sind

Tabellenart

  • Bestimmt sowohl die Verwaltung und interne Speicherung von internen Tabellen als auch den Zugriff auf einzelene Tabelleneinträge
  • Warum ist dies relevant? Die unterschiedlichen Ansätze beim Zugriff auf die Daten können eine bedeutende Auswirkung auf die Leistung haben.
  • Für den Zugriff auf interne Tabellen gibt es zwei Arten:
  • Zugriff über Index: Auf eine Zeile einer internen Tabelle wird über ihre Zeilennummer zugegriffen.

  • Zugriff über Schlüssel: Eine Zeile einer internen Tabelle wird über eine Suche nach bestimmten Werten in bestimmten Spalten adressiert. Die durchsuchten Spalten können sowohl Schlüsselspalten als auch Nicht-Schlüsselspalten sein.

  • Es gibt drei Tabellenarten:
Kategorie Details Verwendung Hinweise
STANDARD - der Inhalt wird in keiner spezifischen Sortierreihenfolge gespeichert (er kann aber mit SORT sortiert werden), kann aber einen internen linearen Index haben (dies gilt auch für sortierte Tabellen und beiden heißen daher Indextabellen) \lbr \lbr - darauf kann über Index und Schlüssel zugegriffen werden \lbr \lbr - der Schlüssel ist nie eindeutig und daher sind doppelte Einträge immer erlaubt; das Hinzufügen von neuen Zeilen ist einigermaßen schnell, da keine Prüfung bei einem existierenden Eintrag stattfinden muss \lbr \lbr - eine Standardtabelle kann sogar mit einem leeren Schlüssel deklariert werden, wenn der Schlüssel nicht nötig ist (Zusatz WITH EMPTY KEY) - wenn der Zugriff auf einzelne Einträge über deren Index oder sequentielle Verarbeitung die Hauptverwendungen sind \lbr \lbr - Daumenregel: wenn in interne Tabellen oft geschrieben wird und nicht sehr oft gelesen, sind Standardtabellen eine gute Wahl; wenn aus internen Tabellen oft gelesen wird und die Tabellen auch oft modifiziert werden, sind sortierte Tabellen und Hash-Tabellen eine gute Wahl - beim Zugriff überwiegend über den Primärtabellenschlüssel sollen große Standardtabellen vermieden werden \lbr \lbr - das Hinzufügen von Zeilen soll über APPEND erfolgen \lbr \lbr - Operationen zum Lesen, Modifizieren und Löschen sollen über die Angabe des Index erfolgen (d.h. über das ABAP-Wort INDEX mit dem relevanten ABAP-Befehl) \lbr \lbr - Im Vergleich zu Hash-Tabellen und sortierten Tabellen haben Standardtabellen die niedrigsten Verwaltungskosten \lbr \lbr - falls der Zugriff über Schlüssel die primäre Zugriffsart ist, sind große Standardtabellen (d.h. über 100 Zeilen) wegen der linearen Suche keine passende Tabellenart
SORTED - der Inhalte von sortierten Tabellen wird immer automatisch über den Tabellenschlüssel sortiert und zwar in aufsteigender Reihenfolge \lbr \lbr - sie besitzen einen internen linearen Index (dies gilt auch für Standardtabellen und daher heißen beide Indextabellen) \lbr \lbr - darauf kann über den Index oder über Schlüssel zugegriffen werden \lbr \lbr - der Schlüssel kann entweder eindeutig oder nicht eindeutig sein - wenn der primäre Verwendungsfall ein schneller Zugriff über den Schlüssel ist \lbr \lbr - auch für die teilweise sequentielle Verarbeitung in Schleifen (beispielsweise bei Angabe des Tabellenschlüssels und der WHERE-Bedingung) oder für den Indexzugriff geeignet; prinzipiell verläuft der Datenzugriff effizienter als in Standardtabellen, da die Daten immer sortiert sind - im Vergleich zu Hash-Tabellen haben sortierte Tabellen niedrigere Verwaltungskosten ( je nach Schlüssellänge und Zeilenanzahl dürfte der Datenzugriff im Kontext einer sortierten Tabelle genauso schnell wie bei einer Hash-Tabelle oder sogar noch schneller. Daher ist einer nicht allzu großen Tabelle und kritischem Speicherplatz einer Hash-Tabelle eine sortierte Tabelle vorzuziehen.)
HASHED - Hash-Tabellen haben keinen linearen Index; sie werden über einen speziellen Hash-Algorithmus verwaltet \lbr \lbr - darauf kann über einen eindeutigen Schlüssel zugegriffen werden - bei großen Tabellen (beispielsweise bei der Verwendung einer internen Tabelle, die einer großen Datenbanktabelle ähnlich ist) \lbr \lbr - beim Schlüsselzugriff als primärem Anwendungsfall und der Möglichkeit ein eindeutiger Schlüssel zu definieren - Duplikate sind nie erlaubt \lbr \lbr - die Antwortzeit ist konstant und von der Anzahl Tabelleinträge unabhängig, da über einen Hash-Algorithmus auf die Tabelleneinträge zugegriffen wird \lbr \lbr - mit Hash-Tabellen ist ein schneller Zugriff garantiert, aber ihr größerer Speicherverbrauch führt zu höheren Verwaltungskosten

Schlüsselattribute

  • Mit dem Schlüssel wird die Tabellenzeile identifiziert; dies darf je nach identifizierter Tabellenzeile eine oder mehrere Tabellenspalten sein
  • Jede interne Tabelle hat einen primären Tabellenschlüssel; optional sind auch sekundäre Schlüssel möglich
  • Der Schlüssel kann eindeutig oder nicht eindeutig (d.h. mehrere Zeilen mit dem gleichen Schlüssel (nämlich Duplikate) dürfen in einer internen Tabelle existieren) sein und die Definition hängt von der Tabellenart ab.

Exkurs: Primär- und Sekundärschlüssel

Weitere Informationen: Tabellenschlüssel.

Beispiele für Primärtabellenschlüssel:

... WITH     UNIQUE KEY comp1 comp2 ...
... WITH     UNIQUE KEY primary_key COMPONENTS comp1 comp2 ...
... WITH NON-UNIQUE KEY primary_key COMPONENTS comp1 comp2 ...
... WITH     UNIQUE KEY primary_key ALIAS key_name ... COMPONENTS ...
... WITH     UNIQUE KEY primary_key COMPONENTS table_line ...

Die Definition des vordefinierten primären Tabellenschlüssels primary_key ist optional. Daher sind das erste und das zweite Beispiel gleich. Beim Hinzufügen eines Alias (mit dem Zusatz ALIAS) kann ein selbstdefinierter Schlüssename für den primären Schlüssel angegeben werden. Mit dem Pseudokomponente table_line kann die ganze Zeile der internen Tabelle als primärer Schlüssel definiert werden. table_line ist jedoch für die Verwendung mit nicht strukturierten Zeilentypen vorgesehen; lange Schlüssel sollen vermieden werden.

... WITH     UNIQUE DEFAULT KEY.
... WITH NON-UNIQUE DEFAULT KEY.

Statt der Angabe einzelner Komponenten für den primären Schlüssel gibt es auch eine implizite Form für die Ermittlung der Komponenten mit DEFAULT KEY:

  • Bei einem strukturieten Zeilentyp besteht der primärer Schlüssel aus Datenfeldern mit einem nicht numerischen elementaren Datentyp.
  • Bei einem nicht strukturierten Zeilentyp oder bei einem Zeilentyp, der kein Tabellentyp ist besteht der primärer Schlüssel aus einer ganzen Tabellenzeile.
  • Wenn der Zeilentyp eine interne Tabelle ist, bleicht der primäre Schlüssel von Standardtabellen leer; bei sortieren Tabellen und Hash-Tabellen meldet das System einen Syntaxfehler.

Bei der Deklaration einer internen Tabelle über DATA und ohne die Definition des primären Schlüssels wird der Zusatz WITH DEFAULT KEY automatisch hinzugefügt; bei der Deklaration über TYPES aber findet dieses Hinzufügen nicht statt. Um spätere ungewollte Konsequenzen zu vermeiden sollten die Schlüssel immer explizit definiert werden. Alternative kann ein leerer Schlüssel für Standardtabellen explizit definiert werden. Hiermit werden Probleme mit den Schlüsseln ohne nicht relevante Schlüssel künstlich definieren zu müssen.

... WITH EMPTY KEY.

Beispiele für Sekundärtabellenschlüssel:

... WITH     UNIQUE HASHED KEY key_name COMPONENTS comp1 comp2 ...
... WITH     UNIQUE SORTED KEY key_name COMPONENTS comp1 comp2 ...
... WITH NON-UNIQUE SORTED KEY key_name COMPONENTS comp1 comp2 ...
... WITH NON-UNIQUE SORTED KEY key_name ALIAS a_name COMPONENTS comp1 comp2 ...

Sekundärschlüssel haben immer selbstdefinierte Namen. Sie dürfen Hash-Schlüssel und sortierte Schlüssel sein, wobei Sekundärschlüssel eindeutig sein müssen. Die Schlüsselkomponenten des Sekundärschlüssels müssen Komponenten des Zeilentyps sein. Falls der Zeilentyp kein strukturierter Datentyp ist, darf nur die Pseudokomponente table_line als einzelne Komponente angegeben werden. Ein Alias darf auch für eine Sekundärschlüssel definiert werden. Damit kann der Sekundärschlüssel sowohl über den selbstdefinierten Namen als auch über den Alias adressiert werden.

Wann sollten Sekundärschlüssel verwendet werden?

  • Um die Geschwindigkeit bei der Datenbeschaffung aus internen Tabellen zu verbessern und die Eindeutigkeit beim Datenzugriff zu garantieren
  • Um einen optimierten Zugriff auf Standardtabellen zu ermöglichen (dabei ist der großer Vorteil, dass vorhandene Standardtabellen um Sekundärschlüssel erweitert werden können, die das Nutzen anderer Tabellentypen bezüglich Geschwindigkeit erhalten)
  • überwiegend bei sehr großen internen Tabellen (mit sehr wenigen nachträglich Änderungen); nicht für kleine interne Tabellen geeignet (weniger als 50 Zeilen), da jeder Sekundärschlüssel zusätzliche Verwaltungskosten erzeugt (durch den Verbrauch von zusätzlichem Speicher)

Beispiele

TYPES itab_type TYPE HASHED TABLE OF spfli
   WITH     UNIQUE KEY carrid connid
   WITH NON-UNIQUE SORTED KEY city_key COMPONENTS cityfrom cityto
   WITH NON-UNIQUE SORTED KEY airp_key COMPONENTS airpfrom airpto.

Für eine Hash-Tabelle wird ein Tabellentyp mit dem Zeilentyp der Datenbanktabelle spfli deklariert. Es werden zwei Komponenten als Primärtabellenschlüssel verwendet. Darüber hinaus werden zwei Sekundärschlüssel mit einem selbstdefinierten Namen deklariert. Im folgenden Beispiel wird wie oben verfahren, der implizite vordefinierte Primärschlüsselname primary_key wird aber explizit erwähnt:

TYPES itab_type TYPE HASHED TABLE OF spfli
  WITH     UNIQUE        KEY primary_key COMPONENTS carrid connid
  WITH NON-UNIQUE SORTED KEY city_key COMPONENTS cityfrom cityto
  WITH NON-UNIQUE SORTED KEY airp_key COMPONENTS airpfrom airpto.

Im folgenden Beispiel wird ein Alias für den Primärschlüssel verwendet.

TYPES itab_type TYPE HASHED TABLE OF spfli
  WITH     UNIQUE        KEY primary_key ALIAS a_name COMPONENTS carrid connid
  WITH NON-UNIQUE SORTED KEY city_key COMPONENTS cityfrom cityto
  WITH NON-UNIQUE SORTED KEY airp_key COMPONENTS airpfrom airpto.

In Ausdrücken und ABAP-Anweisungen können die Schlüssel über die definierten Namen adressiert werden. Mit der Anweisung LOOP als Beispiel können alle Schlüssel mit dem Zusatz USING KEY und dem Namen adressiert werden. Bei den Primärschlüsseln können entweder primary_key oder der selbsdefinierte Alias verwendet werden.

LOOP AT itab INTO wa USING KEY ...
...
ENDLOOP.

Arbeiten mit internen Tabellen

Interne Tabellen anlegen

Die Empfehlung bei der Deklaration von internen Tabellen ist das Anlegen einer internen Tabellen mit diesem Muster in einem Programm:

  • Definition eines strukturierten Datentyps
  • Definition eines internen Tabellentyps
  • Anlegen einer Variable, d.h. die interne Tabelle, die diesen Typ referenziert.

Interne Tabellen, die über eine Kombination der Anlage der Variablen und der Definition des Tabellentyps in einem Schritt sind auch möglich. Wenn die strukturierten Daten und interne Datentype global im DDIC verfügbar sind, ist keine lokale Definitoin innerhalb eines Programs nötig. Im folgenden Beispiel werden das Muster und weitere Beispiele der Deklaration von internen Tabellen und Typen gezeigt, wobei die lokale Definition von strukturierten Daten und internen Tabellentypen Demonstrationszwecken dient.

Beispiel

Im folgenden DEMO_CS_ITAB entnommenen Quelltextausschnitt werden verschiedene interne Tabellendefinitionen demonstriert.

Interne Tabellen füllen

Es wird über eine vorhandene Struktur (lv_struc) und den Operator VALUE eine interne Tabelle um eine Zeile erweitert. Vorhandene Werte in der internen Tabelle werden so geleert.

itab = VALUE #( ( lv_struc ) ).

Über den Operator VALUE kann die interne Tabelle ohne vorhandene Struktur direkt um eine Zeile erweiteret werden. Die zusätzlichen Klammern kennzeichnen eine zusätzliche Tabellenzeile. Wie weiter unten gezeigt dürfen so auch weitere Tabellenzeilen der internen Tabelle hinzugefügt werden. Mit dem Zeichen # wird im Beispiel unten gekennzeichnet, dass der Zeilentyp aus der Tabelle itab abgeleitet werden kann, d.h. die Zeilen und daher auch die in den Klammern hinter dem Zeichen # angegebenen Komponenten und Werte automatisch den Zeilentyp von itab übernehmen. Es ist auch möglich, einen Zeilentyp an dieser Stelle vor den Klammern, um den Typ zu ermitteln, falls er nicht abgeleitet werden kann. Im zweiten Beispiel wird eine interne Tabelle inline deklariert. Ihr wird ein Zeilentyp über VALUE und den angegebenen Typ (dtype) zugeordnet.

itab = VALUE #( ( comp1 = a comp2 = b ... ) ).

DATA(some_itab) = VALUE dtype( ( comp1 = a comp2 = b ... ) ).

Mehrere Zeilen direkt mithilfe des Operators VALUE hinzufügen

itab = VALUE #( ( comp1 = a comp2 = b ... )
                ( comp1 = c comp2 = d ... )
                ( comp1 = e comp2 = f ... ) ).

Bei Verwendung der Zuordnungen oben (itab = ...) wird die interne Tabelle initialisiert und der vorhandene Inhalt gelöscht. Mit dem Zusatz BASE können neue Zeilen ohne das Löschen des vorhandenen Inhalts hinzugefügt werden.

itab = VALUE #( BASE itab ( comp1 = a comp2 = b ... )
                          ( comp1 = c comp2 = d ... ) ).

Inhalt aus einer anderen internen Tabelle, die denselben Zeilentyp hat, kopieren. Vorhandener Inhalt wird gelöscht.

itab = itab2.

Exkurs: Kopieren vom Inhalt. Wie ging man früher im ABAP vor? Nicht verwenden! Obsolete Syntax.

MOVE itab2 TO itab.

Es wird über den Operator CORRESPONDING der Inhalt einer anderen internen Tabelle mit einem anderen Zeilentyp kopiert. Vorhandener Inhalt wird gelöscht. Weitere Syntaxoptionen und Information, z.B. die Abbildungsregeln bei der Behandlung von nicht identischen Feldnamen sind in der ABAP-Schlüsselwortdokumentation zu finden..

itab = CORRESPONDING #( itab3 ).

Es wird über den Operator CORRESPONDING der Inhalt einer anderen internen Tabelle mit einem anderen Zeilentyp kopiert; dabei bleibt der vorhandene Inhalt erhalten.

itab = CORRESPONDING #( BASE ( itab ) itab3 ).

Als eine Alternative zum Operator CORRESPONDING können Anweisungen mit CORRESPONDING verwendet werden. Mit dem Zusatz KEEPING TARGET LINES bleibt der Tabelleninhalt erhalten.

MOVE-CORRESPONDING itab3 TO itab.
MOVE-CORRESPONDING itab3 TO itab KEEPING TARGET LINES.

Mehrere Zeilen aus einer Datenbanktabelle über SELECT einer internen Tabelle hinzufügen, beispielsweise auf Basis einer Bedingung. Im unteren Fall wird die interne Tabelle inline angelegt. Falls die Variable existiert, ist sie ... @itab. Es wird in diesem Fall angenommen, dass itab den gleichen Zeilentyp wie die Datenbanktabelle hat. Beachte das Zeichen @ vor der internen Tabelle (siehe Hostausdrücke). Viele weitere Syntaxoptionen für SELECT-Anweisungen sind vorhanden. Mehr Information finden Sie im ABAP-Spickzettel ABAP SQL: Arbeiten mit persistierten Daten in Datenbanktabellen in der ABAP-Schlüsselwortdokumentation.

SELECT FROM dbtab
  FIELDS comp1, comp2 ...
  WHERE ...
  INTO TABLE @DATA(itab_sel).

Es werden über SELECT ... ENDSELECT. und auf Basis einer Bedingung mehrere Zeilen aus einer Datenbanktabelle einer internen Tabelle sequentiell hinzugefügt. In diesem Fall werden die selektierten Daten erst in einer Struktur gespeichert, die weiter verarbeitet werden kann und einer internen Tabelle hinzugefügt.

SELECT FROM dbtab
  FIELDS comp1, comp2 ...
  WHERE ...
  INTO @DATA(struc_sel).

  IF sy-subrc = 0.
    APPEND struc_sel TO itab.
  ...
  ENDIF.
ENDSELECT.

Es werden mehrere Zeilen aus einer Datenbank über SELECT hinzugefügt, beispielsweise über eine Bedingung, wenn die Datenbanktabelle einen anderen Zeilentyp als die interne Tabelle hat. Mit dem Zeichen * wird die Selektion aller Felder gekennzeichnet. In den anderen Beispielen werden spezifische Felder definiert. Mit dem Zusatz APPENDING CORRESPONDING FIELDS INTO TABLE werden die selektierten Daten unten in der Tabelle angehängt ohne dass vorhandene Tabelleneinträge gelöscht werden. Mit dem Zusatz INTO CORRESPONDING FIELDS OF TABLE werden Zeilen hinzugefügt und vorhandene Tabelleneinträge gelöscht.

SELECT FROM dbtab2
  FIELDS *
  WHERE ...
  APPENDING CORRESPONDING FIELDS INTO TABLE @itab.
  "INTO CORRESPONDING FIELDS OF TABLE @itab.

Es werden über SELECT mehrere Zeilen aus einer internen Tabelle einer anderen internen Tabelle hinzugefügt. Es muss ein Aliasname für die interne Tabelle definiert und beachtet werden.

SELECT comp1, comp2, ...
  FROM @itab2 AS it_alias
  INTO TABLE @DATA(itab_sel).

Exkurse mit der Anweisung SELECT

Es werden über einen inneren join Daten aus mehreren Tabelle in einer internen Tabelle kombiniert. Im Beispiel unten werden die Daten einer internen Tabelle und einer Datenbanktabelle über die Anweisung SELECT und den Zusatz INNER JOIN verknüpft. Die Feldliste enthält Felder aus beiden Tabellen. Die Felder werden über ~ referenziert.

SELECT it_alias~comp1, it_alias~comp2, dbtab~comp3 ...
  FROM @itab AS it_alias
  INNER JOIN dbtab ON it_alias~comp1 = dbtab~comp1
  INTO TABLE @DATA(it_join_result).

Es wird über Subqueries eine interne Tabelle aus einer Datenbanktabelle gefüllt. In beiden folgenden Beispielen wird eine interne Tabelle aus einer Datenbanktabelle gefüllt. Im ersten Beispiel wird eine Subquery über die ABAP-Wörtern NOT IN in einer WHERE-Klausel angegeben. Es wird geprüft, ob ein Wert einem Wert aus einer in Klammern angegebenen Wertmenge entspricht. Im zweiten Beispiel wird eine interne Tabelle abhängig von den Daten in einer anderen Tabelle gefüllt. Es wird eine Subquery über das ABAP-Wort EXISTS in einer WHERE-Klausel angegeben. In diesem Fall wird das Ergebnis der aus einer anderen SELECT-Anweisung bestehenden Subquery geprüft, d.h. es wird kontrolliert, ob ein Eintrag basierend auf den angegebenen Bedingungen in einer Tabelle existiert.

SELECT comp1, comp2, ...
  FROM dbtab
  WHERE comp1 NOT IN ( a, b, c ... )
  INTO TABLE @DATA(it_subquery_result1).

SELECT comp1, comp2, ...
  FROM dbtab
  WHERE EXISTS
    ( SELECT 'X' FROM @itab AS itab_alias
      WHERE comp1 = dbtab~comp1 )
  INTO TABLE @DATA(it_subquery_result2).

Es wird über den Zusatz FOR ALL ENTRIES eine interne Tabelle aus einer Tabelle befüllt, basierend auf vorhandenen Daten in einer anderen Tabelle.

Es muss sichergestellt werden, dass die gelesene interne Tabelle nicht initial ist. Die Verwendung einer Subquery wie oben gezeigt ist daher empfohlen: ... ( SELECT ... FROM @itab AS itab_alias WHERE ...).

IF itab IS NOT INITIAL.
SELECT dbtab~comp1, dbtab~comp2, ...
  FROM dbtab
  FOR ALL ENTRIES IN @itab
  WHERE comp1 = @itab-comp1
  INTO TABLE @DATA(it_select_result).
ENDIF.

Zeilen über die Schlüsselwörter APPEND und INSERT hinzufügen

Mit beiden Anweisungen werden ein oder mehrere Datensätze einer internen Tabelle hinzugefügt. Mit APPEND werden Daten unten in der internen Tabelle hinzugefügt und mit INSERT können Tabellen um Zeilen in spezifischen Stellen erweitert werden. Wenn keine Stelle angegeben wird, werden die Zeilen unten in der Tabelle hinzugefügt. Bei INSERT aber wird sy-tabix nicht wie bei APPEND gesetzt. Mehr Details finden Sie hier: APPEND, INSERT.

Hinweise zur Verwendung von APPEND:

  • Standardtabellen: Es werden Zeilen direkt und ohne Prüfung des Inhalts der internen Tabelle angehängt.
  • Sortierte Tabellen: Es werden Zeilen nur dann angehängt, wenn sie zur Sortierreihenfolge passen und bei eindeutigem primärem Tabellenschlüssel nicht zu doppelten Einträgen führen.
  • Hash-Tabellen: Es können keine Zeilen angehängt werden.

Es wird eine Zeile der internen Tabelle hinzugefügt. In diesem Beispiel wird sowohl eine über die VALUE-Operator angelegte Struktur hinzugefügt als auch eine vorhandene Struktur.

APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab.

APPEND lv_struc TO itab.

Es wird ohne Beschaffung von Feldwerten eine initial Zeile einer internen Tabelle hinzugefügt.

APPEND INITIAL LINE TO itab.

Es werden alle Zeilen aus einer anderern internen Tabelle hinzugefügt. Eine Alternative finden Sie im Abschnitt über den VALUE-Operator unten.

APPEND LINES OF itab2 TO itab.

Es werden Zeilen aus einer anderen internen Tabelle mit einem angegebenen Indexbereich hinzugefügt.

APPEND LINES OF itab2 FROM i1 TO i2 TO itab.

Es werden Zeilen in eine interne Tabelle eingefügt. In diesem Beispiel wird sowohl eine über die VALUE-Operator angelegte Struktur eingefügt als auch eine vorhandene Struktur.

INSERT VALUE #( comp1 = a comp2 = b ... ) INTO TABLE itab.

INSERT lv_struc INTO itab.

Es wird ohne Beschaffung von Feldwerten eine initial Zeile in eine internen Tabelle eingefügt.

INSERT INITIAL LINE INTO TABLE itab.

Es werden Zeilen aus einer anderen internen Tabelle eingefügt.

INSERT LINES OF itab2 INTO TABLE itab.

Es werden Zeilen aus einer anderen internen Tabelle mit einem angegebenen Indexbereich eingefügt.

INSERT LINES OF itab2 FROM i1 TO i2 INTO itab.

Es werden Zeilen aus einer anderen internen Tabelle an einer bestimmten Stelle eingefügt. Die Angabe des Bereichs (... FROM ... TO ...) ist hier optional.

INSERT LINES OF itab2 FROM i1 TO i2 INTO itab INDEX 3.

Werte in einer internen Tabelle gruppieren

Mit dem Schlüsselwort COLLECT kann beispielsweise die Werte numerischer Komponenten den entsprechenden Werten in einer internen Tabelle hinzugefügt werden. Es wird hauptsächlich für interne Tabellen mit eindeutigem Primärschlüssel, vor allem Hash-Tabellen, verwendet.

COLLECT VALUE dtype( comp1 = a comp2 = b ... ) INTO itab.

Aus internen Tabellen lesen

Einzelzeile nach Index lesen ...

... über einen Tabellenausdruck. Das gelesene Ergebnis wird in einer eventuell inline deklarierten Variablen gespeichert. Die Zahl in den eckigen Klammern stellt den Index da. Eine nicht gefundene Zeile führt zu einem Fehler. Um einen Laufzeitfehler zu vermeiden kann ein Block TRY ... CATCH ... ENDTRY. Verwendet werden. Die folgenden Beispiele haben diesen Block nicht. Der im dritten Beispiel verwendete Zusatz KEY ... INDEX ... ist optional. Es wird die zu lesende Zeile aus dem primären Tabellenindex ermittelt. Ohne den Zusatz muss die interne Tabelle eine Indextabelle sein.

DATA(lv1) = itab[ i ].

TRY.
  DATA(lv2) = itab[ i ].
  CATCH cx_sy_itab_line_not_found.
  ...
ENDTRY.

DATA(lv3) = itab[ KEY primary_key INDEX i ].

... über eine READ TABLE-Anweisung in einen Arbeitsbereich oder ein Feldsymbol.

Einige der nachfolgenden Beispiele mit READ TABLE zeigen nur eine Option, beispielsweise mit Arbeitsbereich oder Feldsymbol. Das Vorteil des Feldsymbols ist seine Verwendung als Zeiger (im Vergleich zu einer Variablen als Arbeitsbereich, bei dem der Inhalt tatsächlich kopiert wird) und die Leistungsverbesserung. Ein Einlesen in eine Datenreferenzvariable ist ebenfalls denkbar (... REFERENCE INTO ...). Generell sollte das passende Ausgabeverhalten wie im Thema Zielbereich beschrieben gewählt werden.

Der im dritten Beispiel verwendete Zusatz USING KEY ist optional. Es wird die zu lesende Zeile aus dem primären Tabellenindex ermittelt. Ohne den Zusatz muss die interne Tabelle eine Indextabelle sein.

READ TABLE itab INTO DATA(wa1a) INDEX i.

READ TABLE itab ASSIGNING FIELD-SYMBOL(<fs1>) INDEX i.

READ TABLE itab INTO DATA(wa1b) INDEX i USING KEY primary_key.

Einzelkomponente nach Index lesen ...

... über einen Tabellenausdruck.

DATA(lv3) = itab[ i ]-comp1.

... nachdem eine Zeile über eine READ TABLE-Anweisung in einen Arbeitsbereich oder ein Feldsymbol gelesen wird.

READ TABLE itab INTO DATA(wa2) INDEX i.
DATA(lv4) = wa2-comp1.

READ TABLE itab ASSIGNING FIELD-SYMBOL(<fs2>) INDEX i.
DATA(lv5) = <fs2>-comp1.

Einzelzeile über Tabellenschlüssel lesen

Es wird eine Zeile über den Primärschlüssel (oder Alias wenn vorhanden) gelesen. In den Beispielen wird das Lesen einer Zeile über den explizit angegebenen Tabellenschlüssel gezeigt (in diesem Fall der Primärschlüssel) mit beiden Tabellenausdrücken und READ TABLE Anweisungen. Bei Verwendung von Tabellenausdrücken ist der Zusatz COMPONENTS optional. Dies gilt nicht für READ TABLE-Anweisungen wenn in diesem Kontext der Tabellenschlüssel explizit angegeben wird. Es ist aber möglich, hier auf den Zusatz COMPONENTS und den expliziten Tabellenschlüssel zu verzichten. In diesem Fall wird der Primärtabellenschlüssel verwendet und alle dem Primärschlüssel zugeordneten Komponenten müssen angegeben werden.

DATA(lv6) = itab[ KEY primary_key COMPONENTS comp1 = a ... ].

DATA(lv_alias) = itab[ KEY pkey_alias COMPONENTS comp1 = a ... ]. "alias

DATA(lv7) = itab[ KEY primary_key comp1 = a ... ].

READ TABLE itab INTO DATA(wa) WITH TABLE KEY
    primary_key COMPONENTS comp1 = a ... .

READ TABLE itab INTO DATA(wa) WITH TABLE KEY comp1 = a ... .

Es wird eine Zeile über den Sekundärschlüssel (oder sein Alias wenn vorhanden) gelesen. Es gilt die gleiche Syntax wie oben, mit dem Schlüsselnamen hinter KEY.

DATA(lv9) = itab[ KEY sec_key COMPONENTS comp2 = b ... ].

DATA(lv10) = itab[ KEY sec_key_alias COMPONENTS comp2 = b ... ].

READ TABLE itab INTO DATA(wa4) WITH TABLE KEY sec_key COMPONENTS comp2 = b ...

Einzelzeile über freien Schlüssel lesen ...

... über einen Tabellenausdruck und READ TABLE-Anweisungen. Die angegebenen Komponenten müssen keinem Tabellenschlüssel zugeordnet sein.

DATA(lv11) = itab[ comp3 = c comp4 = d ... ].

READ TABLE itab INTO DATA(wa4) WITH KEY comp3 = c comp4 = d ...

Mehrere Zeilen lesen mithilfe von Schleifen

Es werden alle Tabellenzeilen hintereinander sequentiell gelesen, beispielsweise in einen Arbeitsbereich. Eventuell kann man auf einen Zusatz zur Anweisung LOOP verzichten, d.h. nur LOOP AT itab. ... ENDLOOP.. In diesem Fall werden alle Zeilen der internen Tabelle sequentiell gelesen. Innerhalb der Anweisung LOOP ... ENDLOOP werden die Anweisungen gelesen, die jede Tabellenzeile verarbeiten.

LOOP AT itab INTO DATA(wa5).
  ...
ENDLOOP.

Es werden mehrere Zeilen einer Tabelle in einen Arbeitsbereich durch Angabe eines Indexbereichs sequentiell gelesen.

LOOP AT itab INTO DATA(wa6) FROM i1 TO i2.
  ...
ENDLOOP.

Es werden mehrere Zeilen einer Tabelle in ein Feldsymbol durch Angabe einer Bedingung sequentiell gelesen.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs3>) WHERE comp1 <> a AND comp2 < i ...
  ...
ENDLOOP.

Es werden mehrere Zeilen einer Tabelle in ein Feldsymbol über einen Schüssel (Primär- oder Sekundärschlüssel) sequentiell gelesen.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs4>) USING KEY sec_key.
  ...
ENDLOOP.

Es werden mehrere Zeilen einer Tabelle ohen Tabellenfeldwerte sequentiell gelesen, beispielsweise wenn nur Interesse an Systemfeldern besteht. Die WHERE-Klausel muss auch definiert sein.

LOOP AT itab TRANSPORTING NO FIELDS WHERE comp1 = ...
  ...
ENDLOOP.

Es werden mehrere Zeilen einer Tabelle beim Gruppieren sequentiell gelesen, d.h. es werden Gruppen von Zeilen mit identischen Werten in angegebenen Feldern gebildet. Eine Schleife über die Gruppe selbst ist eventuell auch wünschenswert.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs>) GROUP BY ...
  ...
ENDLOOP.
...
LOOP AT GROUP <fs> ASSIGNING FIELD-SYMBOL(<fs2>) ...
  ...
ENDLOOP.

Interne Tabellen sortieren

Standardtabellen und Hash-Tabellen können über das Schlüsselwort SORT unterschiedlich sortiert werden, beispielsweise durch die Angabe einer Sortierreihenfolge und eine Komponente.

SORT itab ASCENDING.
SORT itab DESCENDING.
SORT itab BY comp1 ASCENDING.
SORT itab BY comp2 DESCENDING.

Interne Tabellen modifizieren

Modifizieren ...

... einer ganzen Zeile aus einem Arbeitsbereich oder einer vorhandenen Struktur. Der Arbeitsbereich oder Struktur muss kompatibel zum Zeilentyp der internen Tabelle sein. Es wird die erste gefundene Zeile der internen Tabelle verarbeitet, deren Werte in den Spalten des verwendeten Tabellenschlüssels mit denen der entsprechenden Komponenten des Arbeitsbereiches oder der Struktur. Sind die Schlüsselfelder im Arbeitsbereich leer, wird kein Eintrag verarbeitet.

MODIFY TABLE itab FROM VALUE #( comp1 = a comp2 = b ... ).

MODIFY TABLE itab FROM lv_struc.

... einer ganzen Zeile aus einem Arbeitsbereich durch die Angabe eines Index. Es wird nur MODIFY verwendet und nicht wie oben MODIFY TABLE.

MODIFY itab FROM VALUE #( comp1 = a comp2 = b ... ) INDEX i.

... spezifischer Felder einer Zeile ohne das Überschreiben anderer Felder. Im Beispiel unten wird der Zusatz INDEX verwendet. Es werden nur die Felder geändert, die nach dem Zusatz TRANSPORTING angegeben sind.

MODIFY itab FROM VALUE #( comp1 = a comp2 = b ... ) INDEX i TRANSPORTING comp1 comp2.

... einer auf einer Bedingung basierenden Zeile. Im Beispiel unten wird der Zusatz TRANSPORTING verwendet.

MODIFY itab FROM VALUE #( comp1 = a comp2 = b ... ) TRANSPORTING    comp1 comp2 WHERE comp2 < ...

... einer Zeile über die Angabe eines Tabellenschlüssels. Der Arbeitsbereich oder Struktur muss kompatibel zum Zeilentyp der internen Tabelle sein. Es wird die erste gefundene Zeile der internen Tabelle verarbeitet, deren Werte in den Spalten des verwendeten Tabellenschlüssels mit denen der entsprechenden Komponenten des Arbeitsbereiches oder der Struktur. Sind die Schlüsselfelder im Arbeitsbereich leer, wird kein Eintrag verarbeitet. Im Beispiel unten wird auch der Zusatz TRANSPORTING verwendet.

MODIFY TABLE itab FROM VALUE #( comp1 = a comp2 = b ... )
  USING KEY sec_key TRANSPORTING comp2 ...
MODIFY TABLE itab FROM lv_struc.

Mehr Information zur Anweisung MODIFY finden Sie unter: MODIFY.

Modifizieren eines Tabelleneintrags ...

... in einer spezifischen Zeile über die Angabe des Index.

itab[ i ]-comp1 = ...

... über einen Schlüsselausdruck. Oben sind weitere Beispiele möglicher Schlüsselausdrücke, d.h. mit Primär- oder Sekundärschlüssel.

itab[ comp1 = a comp2 = b ... ]-comp1 = ...

Modifizieren mehrerer Tabelleneinträge ...

... über eine Schleife.

Die Anweisung LOOP darf um verschiedene Optionen erweitert werden, z.B. über das Setzen einer Bedingung. Weitere Optionen sind im Abschnitt Aus internen Tabellen lesen oben aufgeführt. Das gleiche Ergebnis kann eventuell auch durch anderer Optionen erreicht werden, beispielsweise über einen Tabellenausdruck oder eine MODIFY-Anweisung innerhalb einer Schleife. Bei beiden Alternativen ist bei der der Arbeit mit einem impliziten Index Vorsicht geboten. Daher wird eine explizite Angabe des Tabellenindex empfohlen.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs>).
  <fs>-comp1 = y.
  <fs>-comp2 = z.
  ...
ENDLOOP.

Löschen ...

... einer Zeile über eine explizite Schlüsselangabe. Bei Referenzieren von Primärschlüsseln kommen die folgenden beiden Beispiele als Alternativen in Betracht. Bei der ersten Anweisung wird der Primärschlüssel über den Zusatz COMPONENTS explizit angegeben. Im zweiten Beispiel ist der Zusatz COMPONENTS bei einer vollständigen Angabe der Primärschlüsselkomponenten optional.

DELETE TABLE itab WITH TABLE KEY primary_key
    COMPONENTS comp1 = ...

DELETE TABLE itab WITH TABLE KEY comp1 = ...

... einer Zeile aus einem Arbeitsbereich oder einer Struktur über die implizite Angabe des Schlüssels. Der Schlüssel wird innerhalb des Arbeitsbereichs implizit angegeben.

DELETE TABLE itab FROM VALUE #( comp1 = ...).

... einer Zeile über den Index.

DELETE itab INDEX i.

... mehrere Zeile durch Angabe eines Indexbereichs.

DELETE itab FROM i1 TO i2.

... mehrere Zeilen durch Angabe einer Bedingung.

DELETE itab WHERE comp1 < i ...

... benachbarte Duplikate. Die Duplikate müssen tatsächlich Nachbarn in der Tabelle sein. Standardtabellen können vor einer solchen Löschung sortiert werden.

DELETE ADJACENT DUPLICATES FROM itab.

... Werte einer gesamten Spalte mithilfe einer Schleife.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<del>).
  CLEAR <del>-comp.
ENDLOOP.

Mehr Information zur Anweisung DELETE finden Sie unter: DELETE.

... einer vollständigen Tabelle, d.h. es wird der ganze Inhalt über die Schlüsselwörter CLEAR oder FREE entfernt. Bei der Verwendung von FREE wird auch der durch die interne Tabelle besetzte Speicherbereich freigegeben. Dies gilt nicht für CLEAR, bei dem die Performance entsprechend verbessert wird. Weitere Information finden Sie here: CLEAR, FREE.

CLEAR itab.

FREE itab.

Interne Tabellenfunktionen

Weitere Informationen: Tabellenfunktionen.

line_exists( ): Es wird geprüft, ob eine Zeile vorhanden ist

IF line_exists( itab[ comp1 = a ... ] ).
  ...
ENDIF.

lines( ): Es wird geprüft, wie viele Zeilen in einer internen Tabelle vorhanden sind. Die Funktion gibt eine ganze Zahl zurück.

DATA(itab_lines) = lines( itab ).

line_index( ): Es wird der Index einer bestimmten Zeile geprüft Die Funktion gibt eine ganze Zahl zurück.

DATA(idx) = line_index( itab[ comp1 = a ...] ).

Exkurs: Konstruktorausdrücke

Operator VALUE

Es werden Zeilen aus anderen Tabellen über den Zusatz LINES OF hinzugefügt. Ohne den Zusatz BASE wird vorhandener Inhalt gelöscht. Der Zeilentyp der anderen internen Tabelle muss dem Typ der internen Zieltabelle entsprechen.

itab = VALUE #( ( comp1 = a comp2 = b ...)
                ( comp1 = a comp2 = b ...)
                ( LINES OF itab2 )
                ... ).

Operator CORRESPONDING

Es werden Daten aus einer tiefen internen Tabelle in eine andere tiefe interne Tabelle kopiert. Bei Verwendung es Zusatzes BASE bleibt der Inhalt erhalten. Siehe auch die alternativen MOVE-CORRESPONDING-Anweisungen.

itab_nested2 = CORRESPONDING #( DEEP itab_nested1 ).
itab_nested2 = CORRESPONDING #( DEEP BASE ( itab_nested2 ) itab_nested1 ).

MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES.
MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES KEEPING TARGET LINES.

Operatoren COND und SWITCH

Es werden mehrere Tabelleneinträge basierend auf einer Bedingung innerhalb einer Schleife modifiziert.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs5>).
  <fs5>-comp5 = COND #( WHEN <fs5>-comp5 = a
                        THEN b
                        ELSE c ).
  <fs5>-comp6 = COND #( WHEN <fs5>-comp6 < d
                        THEN e
                        ELSE f ).
  <fs5>-comp7 = COND #( WHEN <fs5>-comp7 < g AND <fs5>-comp6 > h
                        THEN i
                        ELSE j
  ...
ENDLOOP.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs6>).
  <fs6>-comp5 = SWITCH #( <fs6>-comp5 WHEN a
                                      THEN b
                                      ELSE c).
  <fs6>-comp6 = SWITCH #( <fs6>-comp6 WHEN d
                                      THEN e
                                      ELSE f).
  ...
ENDLOOP.

Operator FILTER

Es wird eine interne Tabelle angelegt, indem Daten aus einer andern internen Tabelle kopiert wird und Zeilen, die der WHERE-Bedingung nicht entsprechen, herausgefiltert werden. Es wird eine interne Tabelle gefiltert (d.h. Daten aus internen Tabellen extrahiert) ....

... über eine Bedingung.

DATA(filter1) = FILTER #( itab WHERE comp1 < i ).

... über eine Bedingung mit dem Zusatz EXCEPT, der Daten gemäß der Bedingung ausschließt.

DATA(filter2) = FILTER #( itab EXCEPT WHERE comp1 < i ).

... über eine Filtertabelle.

DATA(filter3) = FILTER #( itab IN filter_tab WHERE comp1 < i.

Iterationen mit FOR

Es werden Werte (einer Spalte in) einer internen Tabelle abgerufen. Im Beispiel unten stellt ls1 eine Iterationsvariable dar, die die Daten während der Tabellenschleife hält. Anders als in LOOP-Anweisungen ist kein Debugging für die sequentielle Verarbeitung möglich. Die zurückzugebenden Komponenten, und daher auch die Tabellenzeile, werden vor der schließenden Klammer innerhalb eines Klammerpaares angegeben. Im Fall unten handelt es sich um eine Komponenten, es dürfen aber auch mehrere sein. Im Demonstrationsprogramm Arbeiten mit internen Tabellen werden weitere Optionen mit FOR behandelt.

DATA(lv) = VALUE dtype( FOR ls1 IN itab ( ls1-comp1 ) ).

Es werden Werte (einer Spalte in) einer internen Tabelle basierend auf der Bedingung abgerufen.

DATA(lv2) = VALUE dtype( FOR ls2 IN itab WHERE ( comp1 < i ) ( ls2-comp1 ) ).

Demonstrationsprogramm

Im Beispiel Arbeiten mit internen Tabellen werden die oben erwähnten syntaktischen Optionen in einem Programm demonstriert.






General Data in Customer Master   BAL Application Log Documentation  
Diese Dokumentation steht unter dem Copyright der SAP AG.

Length: 56532 Date: 20240605 Time: 201951     sap01-206 ( 660 ms )