Erste Schritte
Grundlegende Methoden und Konzepte anwenden
Mit lokalen Klassen arbeiten
Daten aus der Datenbank lesen
Mit strukturierten Datenobjekten arbeiten
Mit komplexen internen Tabellen arbeiten
Datenbankänderungen mit Business Objects implementieren
Das ABAP-RESTful-Anwendungsprogrammiermodell beschreiben

Mit komplexen internen Tabellen arbeiten

Objectives

After completing this lesson, you will be able to:
  • Komplexe interne Tabellen mit Daten füllen.
  • Zugriff auf den Inhalt komplexer interner Tabellen.
  • Verwenden Sie komplexe interne Tabellen in ABAP SQL.

Komplexe interne Tabellen füllen

Wie Sie bereits gelernt haben, lässt sich eine neue Zeile am einfachsten durch die Anweisung APPEND mit einem Datenobjekt, dessen Typ dem Zeilentyp der internen Tabelle entspricht, in eine interne Tabelle einfügen. Dieses Datenobjekt wird auch als „Arbeitsbereich" bezeichnet.

Bei einfachen internen Tabellen kann der in APPEND verwendete Arbeitsbereich eine skalare Variable, eine Konstante oder ein Literal sein. Bei komplexen internen Tabellen muss der Arbeitsbereich strukturiert sein.

Im Beispiel wird die strukturierte Variable connection verwendet, um die interne Tabelle connections zu füllen.

Grundsätzlich gibt es zwei Möglichkeiten, einen Arbeitsbereich connection zu deklarieren:

  • Direkte Referenzierung des Zeilentyps st_connection
  • Indirekte Referenzierung des Zeilentyps über LIKE LINE OF <internal_table>

Die Definition von Arbeitsbereichen mit LIKE LINE OF hat zwei Vorteile:

  • Sie zeigt den Zweck der strukturierten Variablen als Arbeitsbereich für die interne Tabelle.
  • Sie sorgt dafür, dass der Arbeitsbereich zur internen Tabelle passt, auch wenn sich die Definition der internen Tabelle ändert.

Wenn Sie den Arbeitsbereich nicht vor der APPEND-Anweisung füllen, wird die neue Zeile der internen Tabelle mit typspezifischen Initialwerten gefüllt.

Hinweis

Das gleiche Ergebnis erhalten Sie mit der Sondervariante APPEND INITIAL LINE TO <internal_table>. Für diese Variante ist nicht einmal ein Arbeitsbereich erforderlich.

Um den strukturierten Arbeitsbereich zu füllen, können Sie entweder die einzelnen Komponenten füllen oder, wie Sie im Beispiel sehen können, einen Ausdruck VALUE #( ) verwenden.

Wie im Beispiel zu sehen ist, können Sie auch einen Ausdruck VALUE #( ) direkt in der APPEND-Anweisung verwenden. In diesem Fall benötigen Sie keinen Arbeitsbereich.

Notiz

Dies kann sich positiv auf den gesamten Speicherverbrauch Ihres Programms auswirken.

Es gibt eine Variante des Ausdrucks VALUE #( ), die Sie einer internen Tabelle direkt zuweisen können. In dieser Variante von VALUE #( ) werden zusätzliche Klammerpaare verwendet, um die Tabellenzeilen voneinander zu trennen.

Das Code-Beispiel füllt die interne Tabelle carrier mit drei Zeilen, die jeweils einen anderen Wert für carrier_id und carrier_name aufweisen. Dadurch wird die Spalte currency_code nicht erwähnt, sondern mit dem typspezifischen Initialwert gefüllt.

Notiz

Mit der obigen Zuordnung werden alle vorhandenen Tabellenzeilen entfernt, bevor die Tabelle mit den neuen Zeilen gefüllt wird.

Um Daten zwischen namensgleichen Feldern zweier interner Tabellen zu kopieren, verwenden Sie den CORRESPONDING-Operator. Dies funktioniert ähnlich wie CORRESPONDING für Strukturen: Für jede Zeile der internen Quelltabelle legt das System eine neue Zeile in der internen Zieltabelle an und kopiert Daten zwischen namensgleichen Feldern. Quellfelder, für die es kein gleichnamiges Feld im Ziel gibt, werden nicht kopiert. Zielfelder, für die es kein gleichnamiges Feld in der Quelle gibt, werden mit typspezifischen Initialwerten gefüllt.

Im Beispiel enthält die interne Quelltabelle carrier drei Zeilen. Daher enthält die interne Zieltabelle connections nach der Wertzuweisung auch drei Zeilen.

Die Felder carrier_id und carrier_name sind in beiden internen Tabellen vorhanden. Sie werden von der Quelle in das Ziel kopiert. Das Feld currency_code ist nur in der Quelle vorhanden. Es wird nicht kopiert. Die Felder connection_id, airport_from_id und airport_to_id sind nur im Ziel vorhanden. Sie werden mit Initialwerten gefüllt.

Notiz

Wenn die interne Tabelle, die als Ziel dient, vor der Zuweisung Daten enthält, werden diese vom System gelöscht.

Komplexe interne Tabellen debuggen

Probieren Sie es aus: Komplexe interne Tabellen füllen

  1. Legen Sie wie in der ersten Übung dieser Schulung eine neue globale Klasse an, die das Interface IF_OO_ADT_CLASSRUN implementiert.
  2. Kopieren Sie das folgende Code-Snippet in den Implementierungsteil der Methode if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
    TYPES: BEGIN OF st_connection, carrier_id TYPE /dmo/carrier_id, connection_id TYPE /dmo/connection_id, airport_from_id TYPE /dmo/airport_from_id, airport_to_id TYPE /dmo/airport_to_id, carrier_name TYPE /dmo/carrier_name, END OF st_connection. TYPES tt_connections TYPE STANDARD TABLE OF st_connection WITH NON-UNIQUE KEY carrier_id connection_id. DATA connections TYPE tt_connections. TYPES: BEGIN OF st_carrier, carrier_id TYPE /dmo/carrier_id, carrier_name TYPE /dmo/carrier_name, currency_code TYPE /dmo/currency_code, END OF st_carrier. TYPES tt_carriers TYPE STANDARD TABLE OF st_carrier WITH NON-UNIQUE KEY carrier_id. DATA carriers TYPE tt_carriers. * Example 1: APPEND with structured data object (work area) ********************************************************************** * DATA connection TYPE st_connection. " Declare the work area with LIKE LINE OF DATA connection LIKE LINE OF connections. * connection-carrier_id = 'NN'. * connection-connection_id = '1234'. * connection-airport_from_id = 'ABC'. * connection-airport_to_id = 'XYZ'. * connection-carrier_name = 'My Airline'. " Use VALUE #( ) instead assignment to individual components connection = VALUE #( carrier_id = 'NN' connection_id = '1234' airport_from_id = 'ABC' airport_to_id = 'XYZ' carrier_name = 'My Airline' ). APPEND connection TO connections. out->write( `--------------------------------` ). out->write( `Example 1: APPEND with Work Area` ). out->write( connections ). * Example 2: APPEND with VALUE #( ) expression ********************************************************************** APPEND VALUE #( carrier_id = 'NN' connection_id = '1234' airport_from_id = 'ABC' airport_to_id = 'XYZ' carrier_name = 'My Airline' ) TO connections. out->write( `----------------------------` ). out->write( `Example 2: Append with VALUE` ). out->write( connections ). * Example 3: Filling an Internal Table with Several Rows ********************************************************************** carriers = VALUE #( ( carrier_id = 'AA' carrier_name = 'American Airlines' ) ( carrier_id = 'JL' carrier_name = 'Japan Airlines' ) ( carrier_id = 'SQ' carrier_name = 'Singapore Airlines') ). out->write( `-----------------------------------------` ). out->write( `Example 3: Fill Internal Table with VALUE` ). out->write( carriers ). * Example 4: Filling one Internal Table from Another ********************************************************************** connections = CORRESPONDING #( carriers ). out->write( `--------------------------------------------` ). out->write( `Example 4: CORRESPONDING for Internal Tables` ). out->write( data = carriers name = `Source Table CARRIERS:`). out->write( data = connections name = `Target Table CONNECTIONS:`).
  3. Drücken Sie STRG + F3 auf Ihrer Tastatur, um die Klasse zu aktivieren, und F9, um die Konsolen-App auszuführen.
  4. Analysieren Sie die Konsolenausgabe. Debuggen Sie das Programm, und probieren Sie mit dem Quelltext Verschiedenes aus, um sich mit den Konzepten vertraut zu machen.

Zugriff auf komplexe interne Tabellen

Sie haben in diesem Kurs bereits gelernt, wie Sie mithilfe eines internen Tabellenausdrucks eine einzelne Zeile aus einer einfachen internen Tabelle abrufen. Dort wurde ein Indexzugriff verwendet, d.h., die Zeile wurde durch ihre Position in der internen Tabelle identifiziert. Dieser Indexzugriff funktioniert für komplexe interne Tabellen genauso. Für komplexe interne Tabellen werden dagegen interne Tabellenausdrücke mit Schlüsselzugriff wichtig, bei denen die Zeile durch ihren Inhalt identifiziert wird.

Notiz

Obwohl dies als Schlüsselzugriff bezeichnet wird, können beliebige Felder für die Selektion verwendet werden, nicht nur Schlüsselfelder der internen Tabelle. Wenn mehr als eine Zeile die Anforderung erfüllt, geben STANDARD-Tabellen die erste Zeile zurück, d.h. die Zeile mit dem niedrigsten Index.

Im Beispiel wird eine einzelne Zeile aus der internen Tabelle connections gelesen. Der Schlüssel dieser internen Tabelle besteht aus den Feldern carrier_id und connection_id, aber der Schlüsselzugriff verwendet airport_from_id und airport_to_id, um die Zeile zu identifizieren. Die interne Tabelle enthält zwei Verbindungen vom Flughafen SFO zu SIN, sodass die erste davon zurückgegeben wird.

Beachten Sie, dass die ABAP-Laufzeit die Ausnahme CX_SY_ITAB_LINE_NOT_FOUND auslöst, wenn keine der Zeilen die Bedingung erfüllt. Behandeln Sie diese Ausnahme zur Vermeidung von Laufzeitfehlern in einer Struktur TRY … CATCH … ENDTRY.

Wenn Sie mehrere Zeilen einer internen Tabelle verarbeiten möchten und diese unter Angabe von Feldern identifizieren möchten, verwenden Sie LOOP AT <interne Tabelle> INTO <Ziel> WHERE <Bedingung>. Die WHERE-Bedingung kann eine beliebige Anzahl konstituierender Ausdrücke enthalten, die durch AND und OR verknüpft sind. Innerhalb der Ausdrücke können Sie nicht nur das Gleichheitszeichen (=), sondern auch die Operatoren >, >=, <, <=, <> und BETWEEN verwenden.

Nach dem Einlesen des Inhalts einer Tabellenzeile in einen Arbeitsbereich möchten Sie unter Umständen Änderungen aus dem Arbeitsbereich zurück in die interne Tabelle schreiben. Eine Möglichkeit hierfür ist die Anweisung MODIFY TABLE.

Diese Anweisung ist ein Schlüsselzugriff, da das System den Inhalt der Schlüsselfelder im Arbeitsbereich verwendet, um die zu ändernde Tabellenzeile zu identifizieren. Sie überschreibt dann diese Tabellenzeile mit den Inhalten des Arbeitsbereichs.

Im Beispiel enthält der Arbeitsbereich carrier den Wert 'JL' im Schlüsselfeld carrier_id. Anhand dieses Werts identifiziert das System die zweite zu aktualisierende Zeile. Diese Zeile wird dann mit den Werten aus dem Arbeitsbereich aktualisiert.

Notiz

Mit MODIFY TABLE können nur Nicht-Schlüsselfelder geändert werden. Die Anweisung unterstützt keine Änderungen an Schlüsselfeldern.

Die MODIFY -Anweisung (ohne Schlüsselwort TABLE!) unterscheidet nicht zwischen Schlüsselfeldern und Nicht-Schlüsselfeldern. Sie überschreibt die gesamte Tabellenzeile mit neuen Werten aus dem Arbeitsbereich. Diese Anweisung gilt als Indexzugriff, da die zu aktualisierende Zeile durch ihre Position in der internen Tabelle identifiziert wird. In der Regel wird der Index explizit mit dem Zusatz INDEX, gefolgt von einem ganzzahligen Argument (Literal, Konstante, Variable, Ausdruck), angegeben.

Notiz

Es gibt auch eine spezielle Variante ohne den Zusatz INDEX. Wir werden diese Variante als Nächstes besprechen.

Im Beispiel verwendet die MODIFY -Anweisung den Zusatz INDEX, um die erste Tabellenzeile zu adressieren. In dieser Zeile werden alle Felder mit den Werten aus dem Arbeitsbereich überschrieben, auch das Schlüsselfeld carrier_id.

Es treten häufig Situationen auf, in denen Sie die Inhalte mehrerer oder sogar aller Zeilen einer internen Tabelle bearbeiten müssen. Dazu implementieren Sie eine Schleife über die Tabelle, die jede zu ändernde Zeile nacheinander in einen Arbeitsbereich stellt. Innerhalb der Schleife ändern Sie zunächst den Inhalt des Arbeitsbereichs. Anschließend schreiben Sie die Änderungen mit der MODIFY-Anweisung in die interne Tabelle zurück.

Notiz

Wenn Sie Ihre Änderungen nicht zurück in die Tabelle schreiben, gehen die Änderungen verloren, wenn der Arbeitsbereich mit den Daten aus der nächsten Zeile gefüllt wird.

Im Beispiel liest die Schleife alle Zeilen der internen Tabelle carriers, für die das Feld currency_code noch nicht gefüllt ist. Dies ist bei den letzten beiden Zeilen der Fall. Für jede dieser Zeilen ersetzt das Programm den Initialwert im Feld currency_code durch den neuen Wert „USD". Schließlich wird die aktuelle Zeile mithilfe der MODIFY-Anweisung mit den aktualisierten Werten überschrieben.

Anstatt den Index explizit anzugeben, wird im Quelltextbeispiel eine Kurzform der MODIFY-Anweisung verwendet, bei der der Zusatz INDEX fehlt. Diese Kurzform ist nur zwischen LOOP … ENDLOOP erlaubt. Nur dort kann das System implizit die Zeile aktualisieren, an der es gerade arbeitet.

Wenn Sie versuchen, MODIFY ohne INDEX außerhalb von LOOP … ENDLOOP zu verwenden, weiß das System nicht, welche Zeile bearbeitet werden soll, und löst einen nicht abfangbaren Laufzeitfehler aus. Um solche Laufzeitfehler zu vermeiden, achten Sie darauf, die zugehörige Warnung der Syntaxprüfung nicht zu ignorieren.

Try It Out: Zugriff auf komplexe interne Tabellen

  1. Legen Sie wie bei der ersten Übung dieses Kurses eine neue globale Klasse an, die das Interface IF_OO_ADT_CLASSRUN implementiert.
  2. Kopieren Sie das folgende Code-Snippet in den Implementierungsteil der Methode if_oo_adt_classrun~main( ):
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
    TYPES: BEGIN OF st_connection, carrier_id TYPE /dmo/carrier_id, connection_id TYPE /dmo/connection_id, airport_from_id TYPE /dmo/airport_from_id, airport_to_id TYPE /dmo/airport_to_id, carrier_name TYPE /dmo/carrier_name, END OF st_connection. TYPES tt_connections TYPE SORTED TABLE OF st_connection WITH NON-UNIQUE KEY carrier_id connection_id. DATA connections TYPE tt_connections. DATA connection LIKE LINE OF connections. TYPES: BEGIN OF st_carrier, carrier_id TYPE /dmo/carrier_id, currency_code TYPE /dmo/currency_code, END OF st_carrier. DATA carriers TYPE STANDARD TABLE OF st_carrier WITH NON-UNIQUE KEY carrier_id. DATA carrier LIKE LINE OF carriers. * Preparation: Fill internal tables with data ********************************************************************** connections = VALUE #( ( carrier_id = 'JL' connection_id = '0408' airport_from_id = 'FRA' airport_to_id = 'NRT' carrier_name = 'Japan Airlines' ) ( carrier_id = 'AA' connection_id = '0017' airport_from_id = 'MIA' airport_to_id = 'HAV' carrier_name = 'American Airlines' ) ( carrier_id = 'SQ' connection_id = '0001' airport_from_id = 'SFO' airport_to_id = 'SIN' carrier_name = 'Singapore Airlines' ) ( carrier_id = 'UA' connection_id = '0078' airport_from_id = 'SFO' airport_to_id = 'SIN' carrier_name = 'United Airlines' ) ). carriers = VALUE #( ( carrier_id = 'SQ' currency_code = ' ' ) ( carrier_id = 'JL' currency_code = ' ' ) ( carrier_id = 'AA' currency_code = ' ' ) ( carrier_id = 'UA' currency_code = ' ' ) ). * Example 1: Table Expression with Key Access ********************************************************************** out->write( `--------------------------------------------` ). out->write( `Example 1: Table Expressions with Key Access` ). out->write( data = connections name = `Internal Table CONNECTIONS: ` ). " with key fields connection = connections[ carrier_id = 'SQ' connection_id = '0001' ]. out->write( data = connection name = `CARRIER_ID = 'SQ' AND CONNECTION_ID = '001':` ). " with non-key fields connection = connections[ airport_from_id = 'SFO' airport_to_id = 'SIN' ]. out->write( data = connection name = `AIRPORT_FROM_ID = 'SFO' AND AIRPORT_TO_ID = 'SIN':` ). * Example 2: LOOP with key access ********************************************************************** out->write( `-------------------------------` ). out->write( `Example 2: LOOP with Key Access` ). LOOP AT connections INTO connection WHERE airport_from_id <> 'MIA'. "do something with the content of connection out->write( data = connection name = |This is row number { sy-tabix }: | ). ENDLOOP. * Example 3: MODIFY TABLE (key access) ********************************************************************** out->write( `-----------------------------------` ). out->write( `Example 3: MODIFY TABLE (key access` ). out->write( data = carriers name = `Table CARRRIERS before MODIFY TABLE:`). carrier = carriers[ carrier_id = 'JL' ]. carrier-currency_code = 'JPY'. MODIFY TABLE carriers FROM carrier. out->write( data = carriers name = `Table CARRRIERS after MODIFY TABLE:`). * Example 4: MODIFY (index access) ********************************************************************** out->write( `--------------------------------` ). out->write( `Example 4: MODIFY (index access)` ). carrier-carrier_id = 'LH'. carrier-currency_code = 'EUR'. MODIFY carriers FROM carrier INDEX 1. out->write( data = carriers name = `Table CARRRIERS after MODIFY:`). * Example 5: MODIFY in a LOOP ********************************************************************** out->write( `----------------------------` ). out->write( `Example 5: MODIFY in a LOOP` ). LOOP AT carriers INTO carrier WHERE currency_code IS INITIAL. carrier-currency_code = 'USD'. MODIFY carriers FROM carrier. ENDLOOP. out->write( data = carriers name = `Table CARRRIERS after the LOOP:`).
  3. Drücken Sie STRG + F3 auf Ihrer Tastatur, um die Klasse zu aktivieren, und F9, um die Konsolen-App auszuführen.
  4. Analysieren Sie die Konsolenausgabe. Debuggen Sie das Programm, und probieren Sie mit dem Quelltext Verschiedenes aus, um sich mit den Konzepten vertraut zu machen.

Komplexe interne Tabellen in ABAP SQL

Die ABAP-SQL-Anweisung SELECT liest Daten aus einer Datenbanktabelle oder einer CDS-View. Wenn Sie die Option SINGLE verwenden, wird genau ein Datensatz aus der Datenbank gelesen, auch wenn mehr Daten vorhanden sind, die die Bedingungen in der WHERE-Klausel erfüllen.

Wie Sie bereits gelernt haben, ist eine Möglichkeit, dieses Einzelsatzergebnis zu erhalten, eine strukturierte Variable nach dem Schlüsselwort INTO.

Wenn Sie SELECT ohne SINGLE verwenden, geben Sie an, dass Sie an allen Datensätzen interessiert sind, die den Bedingungen in der WHERE-Klausel entsprechen. Sie müssen dann sicherstellen, dass Sie mehrere Datensätze empfangen und speichern können. Der offensichtliche Weg, dies zu tun, ist die Verwendung einer komplexen internen Tabelle als Ziel der SELECT -Anweisung. Dies ist möglich, erfordert aber den Zusatz TABLE zwischen dem Schlüsselwort INTO und dem Namen der internen Tabelle.

Im Beispiel möchten wir alle drei Flughäfen lesen, die mit London in Verbindung stehen, und nicht nur einen einzigen von ihnen. Daher wird das Schlüsselwort SINGLE nach SELECT weggelassen, das Schlüsselwort TABLE hinter INTO hinzugefügt und die interne Tabelle airports_full als Ziel der SELECT-Anweisung verwendet.

Das Beispiel verwendet eine explizite Feldliste hinter FIELDS, die den Spalten der internen Tabelle airports_full entspricht. Natürlich können Sie auch FIELDS *, INTO CORRESPONDING FIELDS OF TABLE und Aliasnamen in der Feldliste verwenden.

Das Beispiel verwendet FIELDS * statt einer expliziten Feldliste und INTO CORRESPONDING FIELDS OF TABLE statt INTO TABLE.

Da der Zeilentyp der internen Tabelle flughäfen nur zwei Komponenten AirportID und Name enthält, werden nur die gleichnamigen Felder von der Datenbank gelesen.

Wenn Sie DATA( ) in einer SELECT-Anweisung hinter dem Zusatz INTO TABLE verwenden, deklarieren Sie inline eine interne Tabelle. Der Zeilentyp dieser internen Tabelle wird aus der FIELDS -Klausel abgeleitet. Für Tabellenfelder und View-Elemente ist ein Aliasname optional. Für Ausdrücke in der FIELDS -Klausel ist ein Aliasname obligatorisch, wenn die INTO -Klausel eine Inline-Deklaration enthält.

Notiz

Inline-Deklarationen interner Tabellen werden nur hinter INTO TABLE unterstützt. Inline-Deklarationen können nicht hinter INTO CORRESPONDING FIELDS OF TABLE verwendet werden.
Inline deklarierte interne Tabellen sind immer Standardtabellen ohne Schlüssel. Sortierte Tabellen oder Hash-Tabellen können nicht mit Inline-Deklarationen deklariert werden. Dies kann zu Performanceproblemen führen, wenn Sie die interne Tabelle mit vielen Zeilen füllen und den Schlüsselzugriff sehr häufig verwenden.

Wenn Sie mehrere Datensätze aus der Datenbank lesen, werden einige spezielle SQL-Techniken besonders interessant. Eine dieser Techniken ist die UNION-Richtlinie, um die Ergebnisse mehrerer SELECT-Anweisungen zu kombinieren.

Die Abbildung zeigt die Kombination zweier SELECT-Ergebnisse:

Das erste SELECT -Ergebnis liest ID und NAME aller Carrier mit CurrencyCode = 'GBP'. Der zweite SELECT liest ID und NAME aller Flughäfen mit City = 'London'. Der erste SELECT gibt einen Datensatz zurück, der zweite SELECT gibt drei Datensätze zurück. Anstatt diese Ergebnisse separat abzurufen, werden sie zu einem Ergebnis mit vier Datensätzen kombiniert. Es ist wichtig, darauf hinzuweisen, dass dies innerhalb der Datenbank geschieht.

Voraussetzung für diese Technik ist natürlich, dass die beiden Ergebnisse miteinander kompatibel sind, d.h. dass sie die gleiche Anzahl von Feldern und die gleichen Feldnamen haben. Es ist jedoch nicht notwendig, dass die Typen der Felder identisch sind.

Die ABAP-SQL-Syntax für dieses Beispiel besteht aus zwei SELECT -Anweisungen. Jede SELECT-Anweisung hat ihre eigene FROM-Klausel, FIELDS-Klausel und WHERE-Klausel, aber ganz am Ende gibt es nur eine INTO-Klausel. Die beiden SELECT -Anweisungen sind durch Schlüsselwörter UNION ALL verbunden.

Notiz

Bei UNION statt UNION ALL würde die Datenbank nach Duplikaten suchen und diese eliminieren, bevor das Ergebnis zurückgegeben wird. Wir verwenden UNION ALL, um diese unnötige zusätzliche Last auf der Datenbank zu vermeiden.

Beide Feldlisten bestehen aus drei Elementen, wobei das erste und das zweite Element in beiden FIELDS -Klauseln identische Aliasnamen haben. Das dritte Feld benötigt keinen Alias, da der Feldname in beiden CDS-Views gleich ist.

Notiz

Das erste Element in FIELDS ist ein literaler Text, mit dem wir im kombinierten Ergebnis zwischen Fluggesellschaften und Flughäfen unterscheiden können.

Try It Out: Interne Tabellen in ABAP SQL

  1. Legen Sie wie in der ersten Übung dieses Kurses eine neue globale Klasse an, die das Interface IF_OO_ADT_CLASSRUN implementiert.
  2. Kopieren Sie das folgende Code-Snippet in den Implementierungsteil der Methode if_oo_adt_classrun~main( ):
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
    TYPES: BEGIN OF st_airport, airportid TYPE /dmo/airport_id, name TYPE /dmo/airport_name, END OF st_airport. TYPES tt_airports TYPE STANDARD TABLE OF st_airport WITH NON-UNIQUE KEY airportid. DATA airports TYPE tt_airports. * Example 1: Structured Variables in SELECT SINGLE ... INTO ... ********************************************************************** DATA airport_full TYPE /DMO/I_Airport. SELECT SINGLE FROM /DMO/I_Airport FIELDS AirportID, Name, City, CountryCode WHERE City = 'Zurich' INTO @airport_full. out->write( `-------------------------------------` ). out->write( `Example 1: SELECT SINGLE ... INTO ...` ). out->write( data = airport_full name = `One of the airports in Zurich (Structure):` ). * Example 2: Internal Tables in SELECT ... INTO TABLE ... ********************************************************************** DATA airports_full TYPE STANDARD TABLE OF /DMO/I_Airport WITH NON-UNIQUE KEY AirportID. SELECT FROM /DMO/I_Airport FIELDS airportid, Name, City, CountryCode WHERE City = 'London' INTO TABLE @airports_full. out->write( `------------------------------------` ). out->write( `Example 2: SELECT ... INTO TABLE ...` ). out->write( data = airports_full name = `All airports in London (Internal Table):` ). * Example 3: FIELDS * and INTO CORRESPONDING FIELDS OF TABLE ********************************************************************** SELECT FROM /DMO/I_Airport FIELDS * WHERE City = 'London' INTO CORRESPONDING FIELDS OF TABLE @airports. out->write( `----------------------------------------------------------` ). out->write( `Example 3: FIELDS * and INTO CORRESPONDING FIELDS OF TABLE` ). out->write( data = airports name = `Internal Table AIRPORTS:` ). * Example 4: Inline Declaration ********************************************************************** SELECT FROM /DMO/I_airport FIELDS AirportID, Name AS AirportName WHERE City = 'London' INTO TABLE @DATA(airports_inline). out->write( `----------------------------------------------------------` ). out->write( `Example 4: Inline Declaration after INTO TABLE` ). out->write( data = airports_inline name = `Internal Table AIRPORTS_INLINE:` ). ** Example 4: ORDER BY and DISTINCT *********************************************************************** * * SELECT * FROM /DMO/I_Airport * FIELDS DISTINCT CountryCode * ORDER BY CountryCode * INTO TABLE @DATA(countryCodes). * * out->write( countryCodes ). * Example 5: UNION (ALL) ********************************************************************** SELECT FROM /DMO/I_Carrier FIELDS 'Airline' AS type, AirlineID AS Id, Name WHERE CurrencyCode = 'GBP' UNION ALL SELECT FROM /DMO/I_Airport FIELDS 'Airport' AS type, AirportID AS Id, Name WHERE City = 'London' * ORDER BY type, Id INTO TABLE @DATA(names). out->write( `----------------------------------------------` ). out->write( `Example 5: UNION ALL of Airlines and Airports ` ). out->write( data = names name = `ID and Name of Airlines and Airports:` ).
  3. Drücken Sie STRG + F3 auf Ihrer Tastatur, um die Klasse zu aktivieren, und F9, um die Konsolen-App auszuführen.
  4. Analysieren Sie die Konsolenausgabe. Debuggen Sie das Programm, und probieren Sie mit dem Quelltext Verschiedenes aus, um sich mit den Konzepten vertraut zu machen.

Komplexe interne Tabelle verwenden

In dieser Übung deklarieren Sie ein tabellenartiges Attribut, füllen es mit einer SELECT-Anweisung und greifen auf den Inhalt zu.

Vorlage:

  • /LRN/CL_S4D400_STS_STRUCTURE (globale Klasse)

Lösung:

  • /LRN/CL_S4D400_ITS_ITAB (globale Klasse)

Aufgabe 1: Vorlage kopieren

Kopieren Sie die Vorlageklasse. Alternativ können Sie Ihre Lösung aus der vorherigen Übung kopieren.

Schritte

  1. Kopieren Sie die Klasse /LRN/CL_S4D400_STS_STRUCTURE in eine Klasse in Ihrem eigenen Paket (Namensvorschlag: ZCL_##_ITAB, wobei ## für Ihre Gruppennummer steht).

    1. Öffnen Sie den Quelltext der globalen Klasse /LRN/CL_S4D400_STS_STRUCTURE.

    2. Verknüpfen Sie die View Project Explorer mit dem Editor.

    3. Klicken Sie in der View Project Explorer mit der rechten Maustaste auf die Klasse /LRN/CL_S4D400_STS_STRUCTURE, um das Kontextmenü zu öffnen.

    4. Wählen Sie im Kontextmenü Duplicate ...

    5. Geben Sie den Namen Ihres Pakets in das Feld Package ein. Geben Sie im Feld Name den Namen ZCL_##_ITAB ein, wobei ## für Ihre Gruppennummer steht.

    6. Passen Sie die Beschreibung an, und wählen Sie Next.

    7. Bestätigen Sie den Transportauftrag, und wählen Sie Finish.

Aufgabe 2: Interne Tabelle deklarieren

Deklarieren Sie in der lokalen Klasse ein statisches, tabellenartiges Attribut flughäfen, um Detailinformationen zu allen verfügbaren Flughäfen zu puffern. Definieren Sie zunächst einen privaten Strukturtyp st_flughafen und einen Tabellentyp tt_flughäfen innerhalb der lokalen Klasse.

Schritte

  1. Wechseln Sie in die lokale Klasse lcl_connection.

    1. Wählen Sie in der globalen Klasse Local Types.

  2. Definieren Sie einen privaten Strukturtyp st_flughafen mit den folgenden Komponenten:

    Komponenten des Strukturtyps st_flughafen:

    KomponentennameDatentyp
    AirportID/dmo/airport_id
    Name/dmo/airport_name
    1. Passen Sie den Quelltext wie folgt an:

      Code Snippet
      1234567891011121314
      TYPES: BEGIN OF st_details, DepartureAirport TYPE /dmo/airport_from_id, DestinationAirport TYPE /dmo/airport_to_id, AirlineName TYPE /dmo/carrier_name, END OF st_details. TYPES: BEGIN OF st_airport, AirportId TYPE /dmo/airport_id, Name TYPE /dmo/airport_name, END OF st_airport.
  3. Definieren Sie einen privaten Tabellentyp tt_flughäfen mit den folgenden Eigenschaften:

    Eigenschaften des Tabellentyps tt_flughäfen:

    EigenschaftWert
    Zeilentypst_flughafen
    TabellenartSTANDARD TABLE
    SchlüsseldefinitionNICHT-EINHEITLICHER STANDARDSCHLÜSSEL
    1. Passen Sie den Quelltext wie folgt an:

      Code Snippet
      12345678910
      TYPES: BEGIN OF st_airport, AirportId TYPE /dmo/airport_id, Name TYPE /dmo/airport_name, END OF st_airport. TYPES tt_airports TYPE STANDARD TABLE OF st_airport WITH NON-UNIQUE DEFAULT KEY.
  4. Deklarieren Sie ein neues privates statisches Attribut flughäfen und typisieren Sie es mit dem Tabellentyp tt_flughäfen.

    1. Fügen Sie am Ende der Klassendefinition den folgenden Quelltext hinzu:

      Code Snippet
      123
      CLASS-DATA airports TYPE tt_airports.

Aufgabe 3: Statisches Attribut in einem Klassenkonstruktor füllen

Definieren Sie einen Klassenkonstruktor und implementieren Sie eine SELECT-Anweisung, die alle verfügbaren Flughäfen aus der CDS-View-Entität /DMO/I_Airport in das statische Attribut flughäfen liest.

Schritte

  1. Fügen Sie der lokalen Klasse lcl_connection über einen Quickfix einen Klassenkonstruktor hinzu.

    1. Setzen Sie den Cursor auf den Namen der Klasse, und drücken Sie Strg + 1.

    2. Doppelklicken Sie auf Klassenkonstruktor generieren.

  2. Implementieren Sie im Klassenkonstruktor eine SELECT -Anweisung, die alle Datensätze aus der CDS-View-Entität /DMO/I_Airport in das statische Attribut flughäfen liest.

    1. Navigieren Sie zur Implementierung der Methode class_constructor.

    2. Fügen Sie in der Methodenimplementierung den folgenden Quelltext hinzu:

      Code Snippet
      12345
      SELECT FROM /DMO/I_Airport FIELDS AirportID, Name INTO TABLE @airports.

Aufgabe 4: Zugriff auf den Inhalt der internen Tabelle

Verwenden Sie den Inhalt der internen Tabelle flughäfen in der Methode get_output, um die Flughafennamen zur Ausgabe hinzuzufügen.

Schritte

  1. Navigieren Sie zur Implementierung der Methode get_output.

    1. Fahren Sie wie in den vorangegangenen Übungen fort.

  2. Lesen Sie zu Beginn der Methode die Details des Abflugflughafens in ein strukturiertes Datenobjekt flight.

    Hinweis

    Verwenden Sie einen Tabellenausdruck airports[ ... ] und eine Inline-Deklaration für das Datenobjekt escape.
    1. Fügen Sie am Anfang der Methode den folgenden Code hinzu:

      Code Snippet
      123
      DATA(departure) = airports[ airportID = details-departureairport ].
  3. Ebenso lesen Sie die Details des Zielflughafens in ein strukturiertes Datenobjekt destination.

    1. Passen Sie den Quelltext wie folgt an:

      Code Snippet
      1234
      DATA(departure) = airports[ airportID = details-departureairport ]. DATA(destination) = airports[ airportID = details-destinationairport ].
  4. Verwenden Sie den Komponentennamen der beiden Strukturen, um die Flughafennamen zur Ausgabe hinzuzufügen.

    1. Passen Sie den Quelltext wie folgt an:

      Code Snippet
      1234
      APPEND |Departure: { details-departureairport } { departure-name }| TO r_output. APPEND |Destination: { details-destinationairport } { destination-name }| TO r_output.
  5. Optional: Verzichten Sie auf das strukturierte Datenobjekt und verwenden Sie die Tabellenausdrücke direkt in den Zeichenketten-Templates.

    1. Kommentieren Sie die Codezeilen, in denen Sie die Strukturen für Abfahrt und Ziel füllen.

    2. Ersetzen Sie im Zeichenketten-Template departure-name durch airports[ airportid = details-departureairport ]-name.

    3. Ersetzen Sie destination-name analog durch airports[ airportid = details-destinationairport ]-name.

  6. Aktivieren Sie die Klasse. Führen Sie sie aus, und analysieren Sie die Konsolenausgabe. Prüfen Sie, ob die Ausgabe Daten für alle Attribute anzeigt.

    1. Drücken Sie Strg + F3, um die Klasse zu aktivieren.

    2. Drücken Sie F9, um die Klasse auszuführen.