Introduction
Application des techniques et concepts de base
Utilisation des classes locales
Lecture des données de la base de données
Utilisation d'objets de données structurés
Utilisation de tables internes complexes
Implémentation de mises à jour de base de données à l'aide d'objets de gestion
Description du modèle de programmation d'applications ABAP RESTful

Utilisation de tables internes complexes

Objectives

After completing this lesson, you will be able to:
  • Remplir les tables internes complexes avec des données.
  • Accédez au contenu de tables internes complexes.
  • Utilisez des tables internes complexes dans ABAP SQL.

Remplissage de table interne complexe

Comme vous l'avez déjà appris, la manière la plus simple d'ajouter une nouvelle ligne à une table interne est l'instruction APPEND avec un objet de données dont le type correspond au type de ligne de la table interne. Cet objet de données est parfois appelé espace de travail.

Pour les tables internes simples, l'espace de travail utilisé dans APPEND peut être une variable scalaire, une constante ou un littéral. Pour les tables internes complexes, l'espace de travail doit être structuré.

Dans l'exemple, la connexion de variable structurée est utilisée pour renseigner les connexions de tables internes.

En principe, il existe deux façons de déclarer la connexion à l'espace de travail :

  • Référencer directement le type de ligne st_connection
  • Référencez le type de ligne indirectement à l'aide de LIKE LINE OF <table_interne>.

La définition d'espaces de travail avec LIKE LINE OF présente deux avantages :

  • Elle révèle l'objectif de la variable structurée comme espace de travail pour la table interne.
  • Il garantit que l'espace de travail correspond à la table interne, même si la définition de la table interne change.

Si vous ne renseignez pas l'espace de travail avant l'instruction APPEND, la nouvelle ligne de la table interne sera renseignée avec des valeurs initiales spécifiques au type.

Astuce

Vous obtenez le même résultat avec la variante spéciale APPEND INITIAL LINE TO <table_interne>. Cette variante ne nécessite même pas d'espace de travail.

Pour renseigner l'espace de travail structuré, vous pouvez renseigner les composants individuels ou, comme vous pouvez le voir dans l'exemple, utiliser une expression VALUE #( ).

Comme vous pouvez le voir dans l'exemple, vous pouvez également utiliser une expression VALUE #( ) directement dans l'instruction APPEND. Dans ce cas, vous n'avez pas besoin d'un espace de travail.

Remarque

Cela peut avoir un effet positif sur l'utilisation globale de la mémoire de votre programme.

Il existe une variante de l'expression VALUE #( ) que vous pouvez affecter directement à une table interne. Dans cette variante de VALUE #( ), des paires supplémentaires de parenthèses sont utilisées pour séparer les lignes de table les unes des autres.

L'exemple de code renseigne les supports de table internes avec trois lignes, chacune avec une valeur différente pour carrier_id et carrier_name. Par conséquent, la colonne currency_code n'est pas mentionnée, elle est renseignée avec la valeur initiale spécifique au type.

Remarque

Avec l'affectation ci-dessus, toutes les lignes de table existantes sont supprimées avant que la table ne soit renseignée avec les nouvelles lignes.

Pour copier des données entre des zones portant le même nom de deux tables internes, utilisez l'opérateur CORRESPONDING. Cela fonctionne de la même manière que CORRESPONDING pour les structures : pour chaque ligne de la table interne source, le système crée une nouvelle ligne dans la table interne cible et copie les données entre les zones portant le même nom. Les zones sources pour lesquelles il n'existe aucune zone portant le même nom dans la cible ne sont pas copiées. Les zones cibles pour lesquelles il n'existe pas de zone portant le même nom dans la source sont renseignées avec des valeurs initiales spécifiques au type.

Dans l'exemple, les porteuses de table interne source contiennent trois lignes. Par conséquent, après la valorisation, les connexions de table interne cible contiennent également trois lignes.

Les zones carrier_id et carrier_name existent dans les deux tables internes. Ils sont copiés de la source vers la cible. Le champ currency_code existe uniquement dans la source. Il n'est pas copié. Les champs connection_id, airport_from_id et airport_to_id existent uniquement dans la cible. Elles sont renseignées avec des valeurs initiales.

Remarque

Si la table interne cible contient des données avant l'affectation, le système les supprime.

Comment déboguer des tables internes complexes

Essayer : remplissage des tables internes complexes

  1. Comme dans le premier exercice de ce cours, créez une nouvelle classe globale qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode 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. Appuyez sur CTRL + F3 sur votre clavier pour activer la classe et F9 pour exécuter l'application console.
  4. Analysez la sortie de la console. Déboguer le programme, jouer avec le code source pour se familiariser avec les concepts.

Accès aux tables internes complexes

Plus tôt dans ce cours, vous avez appris à extraire une seule ligne d'une simple table interne à l'aide d'une expression de table interne. À l'époque, nous utilisions un accès à l'index, c'est-à-dire que nous identifiions la ligne par sa position dans la table interne. Cet accès à l'index fonctionne de la même manière pour les tables internes complexes. Cependant, pour les tables internes complexes, les expressions de table interne avec accès par clé deviennent importantes, où vous identifiez la ligne via son contenu.

Remarque

Même s'il s'agit d'un accès par clé, vous pouvez utiliser toutes les zones pour la sélection, et pas seulement les zones clés de la table interne. Si plusieurs lignes remplissent les conditions requises, les tables STANDARD renvoient la première ligne, c'est-à-dire la ligne avec l'index le plus bas.

L'exemple lit une seule ligne à partir des connexions de tables internes. La clé de cette table interne se compose des zones carrier_id et connection_id, mais l'accès à la clé utilise airport_from_id et airport_to_id pour identifier la ligne. La table Interne contient deux liaisons de l'aéroport SFO à SIN, la première d'entre elles est donc retournée.

N'oubliez pas que l'exécution ABAP déclenche l'exception CX_SY_ITAB_LINE_NOT_FOUND si aucune des lignes ne remplit les conditions. Gérez cette exception dans une structure TRY … CATCH … ENDTRY pour éviter les erreurs d'exécution.

Pour traiter plusieurs lignes d'une table interne en indiquant des zones, vous utilisez LOOP AT <table interne> INTO <cible> WHERE <condition>. La condition WHERE peut contenir un nombre illimité d'expressions constitutives jointes à l'aide de AND et OR. Dans les expressions, vous pouvez utiliser non seulement l'opérateur égal (=), mais aussi les opérateurs >, >=, <, <=, <> et BETWEEN.

Après avoir lu le contenu d'une ligne de table dans un espace de travail, vous voulez parfois réécrire les modifications de l'espace de travail dans la table interne. L'instruction MODIFY TABLE est une façon de le faire.

Cette instruction est un accès par clé car le système utilise le contenu des zones clés dans l'espace de travail pour identifier la ligne de table qui doit être modifiée. Il écrase ensuite cette ligne de table avec le contenu de l'espace de travail.

Dans l'exemple, le transporteur de l'espace de travail contient la valeur "JL" dans la zone clé Carrier_id. Sur la base de cette valeur, le système identifie la deuxième ligne à mettre à jour. Cette ligne est ensuite mise à jour avec les valeurs de l'espace de travail.

Remarque

Vous pouvez uniquement modifier les zones non clés avec MODIFY TABLE. L'instruction ne prend pas en charge les modifications des zones clés.

Instruction MODIFY (sans mot-clé TABLE!) ne fait pas la distinction entre les zones clés et les zones non clés. Il écrase l'ensemble de la ligne de table avec les nouvelles valeurs de l'espace de travail. Cette instruction est considérée comme un accès à l'index car la ligne à mettre à jour est identifiée par sa position dans la table interne. Généralement, l'index est spécifié explicitement à l'aide de l'option INDEX suivie d'un argument entier (littéral, constante, variable, expression).

Remarque

Il existe également une variante spéciale sans l'option INDEX. Nous aborderons ensuite cette variante.

Dans l'exemple, l'instruction MODIFY utilise l'option INDEX pour adresser la première ligne de table. Dans cette ligne, toutes les zones sont écrasées par les valeurs de l'espace de travail, même la zone clé carrier_id.

Il arrive souvent que vous deviez modifier le contenu de plusieurs lignes d'une table interne, voire toutes. Pour ce faire, vous implémentez une boucle sur la table, qui place chaque ligne que vous devez modifier successivement dans un espace de travail. Dans la boucle, vous modifiez d'abord le contenu de l'espace de travail, puis réécrivez les modifications dans la table interne à l'aide de l'instruction MODIFY.

Remarque

Si vous ne réécrivez pas vos modifications dans la table, elles seront perdues lorsque l'espace de travail sera renseigné avec les données de la ligne suivante.

Dans l'exemple, la boucle lit toutes les lignes de porteuses de tables internes pour lesquelles la zone currency_code n'est pas encore renseignée. C'est le cas pour les deux dernières lignes. Pour chacune de ces lignes, le programme remplace la valeur initiale dans la zone currency_code par la nouvelle valeur "USD". Enfin, il utilise l'instruction MODIFY pour écraser la ligne actuelle avec les valeurs mises à jour.

Au lieu d'indiquer explicitement l'index, l'exemple de code utilise une forme abrégée de l'instruction MODIFY où l'option INDEX est manquante. Cette forme abrégée est autorisée uniquement entre LOOP … ENDLOOP. C'est seulement là que le système peut implicitement mettre à jour la ligne sur laquelle il travaille actuellement.

Si vous utilisez MODIFY sans INDEX en dehors de LOOP…ENDLOOP, le système ne sait pas quelle ligne modifier et déclenche une erreur d'exécution non interceptable. Pour éviter de telles erreurs d'exécution, assurez-vous de ne pas ignorer l'avertissement lié du contrôle syntaxique !

Essayer : accès aux tables internes complexes

  1. Comme pour le premier exercice de ce cours, créez une nouvelle classe globale qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode 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. Appuyez sur CTRL + F3 sur votre clavier pour activer la classe et F9 pour exécuter l'application console.
  4. Analysez la sortie de la console. Déboguer le programme, jouer avec le code source pour se familiariser avec les concepts.

Tables internes complexes dans ABAP SQL

L'instruction ABAP SQL SELECT lit les données d'une table de base de données ou d'une vue CDS. Lorsque vous utilisez l'option SINGLE, un seul enregistrement est lu dans la base de données, même s'il existe plus de données qui remplissent les conditions de la clause WHERE.

Comme vous l'avez appris précédemment, une façon de recevoir ce résultat d'enregistrement individuel est la variable structurée après le mot-clé INTO.

Si vous utilisez SELECT sans SINGLE, vous indiquez que vous êtes intéressé par tous les enregistrements qui correspondent aux conditions de la clause WHERE. Vous devez ensuite vous assurer que vous pouvez réellement recevoir et stocker plusieurs enregistrements. La méthode la plus évidente consiste à utiliser une table interne complexe comme cible de l'instruction SELECT. Cela est possible, mais l'ajout de TABLE entre le mot-clé INTO et le nom de la table interne est nécessaire.

Dans l'exemple, nous voulons lire les trois aéroports liés à Londres et pas seulement un seul d'entre eux. Par conséquent, nous excluons le mot-clé SINGLE après SELECT, ajoutons le mot-clé TABLE après INTO et utilisons la table interne airports_full comme cible de l'instruction SELECT.

L'exemple utilise une liste de champs explicite après FIELDS qui correspond aux colonnes de la table interne airports_full. Bien entendu, vous pouvez également utiliser FIELDS *, INTO CORRESPONDING FIELDS OF TABLE et les noms d'alias dans la liste de zones.

Cet exemple utilise FIELDS * au lieu d'une liste de zones explicite et INTO CORRESPONDING FIELDS OF TABLE au lieu de INTO TABLE.

Comme le type de ligne de la table interne Aéroports ne contient que deux composantes AirportID et Name, seules les zones avec le même nom sont lues à partir de la base de données.

Si vous utilisez DATA( ) dans une instruction SELECT après l'ajout INTO TABLE, vous déclarez en ligne une table interne. Le type de ligne de cette table interne est dérivé de la clause FIELDS. Pour les zones de table et les éléments de vue, un nom d'alias est facultatif. Pour les expressions de la clause FIELDS, un nom d'alias est obligatoire si la clause INTO contient une déclaration en ligne.

Remarque

Les déclarations en ligne des tables internes ne sont prises en charge qu'après INTO TABLE. Vous ne pouvez pas utiliser de déclarations en ligne après INTO CORRESPONDING FIELDS OF TABLE.
Les tables internes déclarées en ligne sont toujours des tables standard sans clé. Vous ne pouvez pas déclarer des tables triées ou hachées à l'aide de déclarations en ligne. Cela peut entraîner des problèmes de performance si vous renseignez la table interne avec de nombreuses lignes et utilisez beaucoup l'accès à la clé.

Lorsque vous lisez plusieurs enregistrements de la base de données, certaines techniques SQL spéciales deviennent particulièrement intéressantes. L'une de ces techniques est la directive UNION pour combiner les résultats de plusieurs instructions SELECT.

La figure illustre la combinaison de deux résultats SELECT :

Le premier résultat SELECT lit l'ID et le NOM de tous les transporteurs avec CurrencyCode = 'GBP'. Le deuxième SELECT lit l'ID et le NOM de tous les aéroports avec City = 'London'. Le premier SELECT renvoie un enregistrement, le second SELECT renvoie trois enregistrements. Au lieu de récupérer ces résultats séparément, ils sont combinés en un seul résultat avec quatre enregistrements. Il est important de souligner que cela se produit dans la base de données.

Une condition préalable à cette technique est bien entendu que les deux résultats soient compatibles l'un avec l'autre, c'est-à-dire qu'ils aient le même nombre de zones et les mêmes noms de zone. Il est avantageux, bien que cela ne soit pas nécessaire, que les types de zones soient également identiques.

La syntaxe ABAP SQL pour cet exemple se compose de deux instructions SELECT. Chaque instruction SELECT possède sa propre clause FROM, FIELDS et WHERE, mais il n'existe qu'une seule clause INTO à la fin. Les deux instructions SELECT sont connectées par les mots-clés UNION ALL.

Remarque

Avec UNION au lieu de UNION ALL, la base de données recherche et élimine les doublons avant de renvoyer le résultat. Nous utilisons UNION ALL pour éviter cette charge supplémentaire inutile sur la base de données.

Les deux listes de champs se composent de trois éléments, le premier et le deuxième élément ont des noms d'alias identiques dans les deux clauses FIELDS. La troisième zone n'a pas besoin d'un alias car le nom de zone est le même dans les deux vues CDS.

Remarque

Le premier élément de FIELDS est un texte littéral qui permet de faire la distinction entre les compagnies aériennes et les aéroports dans le résultat combiné.

Essayer : tables internes dans ABAP SQL

  1. Comme dans le premier exercice de ce cours, créez une nouvelle classe globale qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode 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. Appuyez sur CTRL + F3 sur votre clavier pour activer la classe et F9 pour exécuter l'application console.
  4. Analysez la sortie de la console. Déboguer le programme, jouer avec le code source pour se familiariser avec les concepts.

Utiliser une table interne complexe

Dans cet exercice, vous déclarez un attribut tabulaire, vous le renseignez à l'aide d'une instruction SELECT et vous accédez au contenu.

Modèle :

  • /LRN/CL_S4D400_STS_STRUCTURE (classe globale)

Solution :

  • /LRN/CL_S4D400_ITS_ITAB (classe globale)

Tâche 1: Copier modèle

Copiez la classe de modèle. Vous pouvez également copier votre solution de l'exercice précédent.

Étapes

  1. Copiez la classe /LRN/CL_S4D400_STS_STRUCTURE dans une classe de votre propre package (nom proposé : ZCL_##_ITAB, où ## correspond à votre numéro de groupe).

    1. Ouvrez le code source de la classe globale /LRN/CL_S4D400_STS_STRUCTURE.

    2. Liez la vue Explorateur de projets à l'aide de l'éditeur.

    3. Dans la vue Explorateur de projets, cliquez avec le bouton droit de la souris sur la classe /LRN/CL_S4D400_STS_STRUCTURE pour ouvrir le menu contextuel.

    4. Dans le menu contextuel, sélectionnez Dupliquer ....

    5. Saisissez le nom de votre package dans la zone Package. Dans la zone Nom, saisissez le nom ZCL_##_ITAB, où ## représente votre numéro de groupe.

    6. Ajustez la description et cliquez sur Suivant.

    7. Confirmez l'ordre de transport et cliquez sur Terminer.

Tâche 2: Déclarer une table interne

Dans la classe locale, déclarez un attribut statique de type table aéroports pour mettre en mémoire tampon les informations détaillées sur tous les aéroports disponibles. Commencez par définir un type de structure privé st_airport et un type de table tt_aéroports dans la classe locale.

Étapes

  1. Passez à la classe locale lcl_connection.

    1. Dans la classe globale, sélectionnez Types locaux.

  2. Définissez un type de structure privéest_airport avec les composants suivants :

    Composants du type de structure st_airport :

    Nom du composantType de données
    AirportID/dmo/airport_id
    Nom/dmo/airport_name
    1. Adaptez le code comme suit :

      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. Définissez un type de table privéett_aéroports avec les propriétés suivantes :

    Propriétés du type de table tt_aéroports :

    PropriétéValeur
    Type de lignest_aéroport
    Type de tableTABLE STANDARD
    Définition de cléCLÉ PAR DÉFAUT NON UNIQUE
    1. Adaptez le code comme suit :

      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. Déclarez un nouvel attribut statique privé Aéroports et saisissez-le avec le type de table tt_aéroports.

    1. À la fin de la définition de classe, ajoutez le code suivant :

      Code Snippet
      123
      CLASS-DATA airports TYPE tt_airports.

Tâche 3: Renseigner l'attribut statique dans un constructeur de classes

Définissez un constructeur de classe et implémentez une instruction SELECT qui lit tous les aéroports disponibles de l'entité de vue CDS /DMO/I_Airport dans l'attribut statique aéroports.

Étapes

  1. Ajoutez un constructeur de classe à la classe locale lcl_connection à l'aide d'un correctif rapide.

    1. Positionnez le curseur sur le nom de la classe et appuyez sur Ctrl + 1.

    2. Double-cliquez sur Générer constructeur de classe.

  2. Dans le constructeur de classe, implémentez une instruction SELECT qui lit tous les ensembles de données de l'entité de vue CDS /DMO/I_Airport dans l'attribut statique aéroports.

    1. Naviguez vers l'implémentation de la méthode class_constructor.

    2. Dans l'implémentation de méthode, ajoutez le code suivant :

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

Tâche 4: Accéder au contenu de la table interne

Utilisez le contenu de la table interne aéroports dans la méthode get_output pour ajouter les noms d'aéroports à la sortie.

Étapes

  1. Naviguez vers l'implémentation de la méthode get_output.

    1. Procédez comme vous l'avez fait dans les exercices précédents.

  2. Au début de la méthode, lisez les détails de l'aéroport de départ dans un objet de données structuré départ.

    Astuce

    Utilisez une expression de table airports[ ... ] et une déclaration en ligne pour le départ de l'objet de données.
    1. Au début de la méthode, ajoutez le code suivant :

      Code Snippet
      123
      DATA(departure) = airports[ airportID = details-departureairport ].
  3. De même, lisez les détails de l'aéroport de destination dans une destination d'objet de données structuré.

    1. Adaptez le code comme suit :

      Code Snippet
      1234
      DATA(departure) = airports[ airportID = details-departureairport ]. DATA(destination) = airports[ airportID = details-destinationairport ].
  4. Utilisez le nom de composant des deux structures pour ajouter les noms d'aéroport à la sortie.

    1. Adaptez le code comme suit :

      Code Snippet
      1234
      APPEND |Departure: { details-departureairport } { departure-name }| TO r_output. APPEND |Destination: { details-destinationairport } { destination-name }| TO r_output.
  5. Facultatif : ignorez l'objet de données structuré et utilisez les expressions de table directement dans les modèles de chaîne.

    1. Commentez les lignes de code dans lesquelles vous renseignez les structures départ et destination.

    2. Dans le modèle de chaîne, remplacez departure-name par airports[ airportid = details-departureairport ]-name.

    3. De même, remplacez destination-name par airports[ airportid = details-destinationairport ]-name.

  6. Activez la classe. Exécutez-la et analysez la sortie de la console. Vérifiez que la sortie affiche des données pour tous les attributs.

    1. Appuyez sur Ctrl + F3 pour activer la classe.

    2. Appuyez sur F9 pour exécuter la classe.