ABAP-Entwicklung

Lesezeit ca. 9 Minuten

In SAP sind relevante Informationen immer auf verschiedene Datenbanktabellen verteilt. Das sorgt für eine sparsame Speicherplatzbelegung und vermeidet redundante Datenhaltung.  Die Programmierung bereitet aber bei der Verarbeitung dieser Daten etwas Mühe. Ein Programmierer muss die Verknüpfungen zwischen den einzelnen Tabellen nachverfolgen. Bei ausgedehnten Sachverhalten kann das durchaus umfangreich werden – und es erfordert ein genaues Verständnis der Zusammenhänge. Eine Vereinfachung dieses Problems in ABAP sind Meshes.

Um die Problematik vieler miteinander in Beziehung stehender Tabellen zu verdeutlichen, stellen Sie sich vor, Sie möchten alle Personen einer bestimmten Organisationseinheit laden. Mit der neuen ABAP-Technik „Meshes“ können diese Zusammenhänge zwischen einzelnen Tabellen zu Beginn der Entwicklung spezifiziert werden. Im weiteren Verlauf der Programmierung kann man dann die einzelnen Verbindungen ohne großen Aufwand  durchlaufen.

Das unten stehende Beispiel soll dies verdeutlichen, dabei werden wie oben beschrieben, alle Personen in einer Organisationseinheit geladen. Abgefragt wird dabei:

  • Der Objekttyp ‚O‘ für Organisationseinheit
  • Die Planvariante
  • Die ID der Organisationseinheit
  • Und die Richtung sowie die Art dieser Verknüpfung


"
" LOOP über alle Verknüpfungen zwischen Organisationseinheiten und Planstellen
"
LOOP AT lt_hrp1001 ASSIGNING FIELDSYMBOL(<fs_orgeh>)
                   WHERE OTYPE = 'O' AND
                         PLVAR = lv_plvar AND
                         OBJID = '01234567' AND
                         RSIGN = 'B' AND
                         RELAT = '003'.
 "
 " LOOP über alle Verknüpfungen zwischen Planstellen und Personen
 "
 LOOP AT lt_hrp1001 ASSIGNING FIELDSYMBOL(<fs_pos>)
                    WHERE OTYPE = 'S' AND
                          PLVAR = <fs_orgeh>-plvar AND
                          OBJID = <fs_orgeh>-sobid AND
                          SUBTY = 'A' AND
                          SCLAS = '008'.

   "
   " LOOP über alle relevanten Personen
   "
   LOOP AT lt_hrp1000 ASSIGNING FIELDSYMBOL(<fs_person>)
                      WHERE OTYPE = 'P' AND
                      PLVAR = <fs_pos>-plvar AND
                      OBJID = <fs_pos>-sobid AND
                      OBJID IN so_persons.
       "Gebe Langtexte zu einer Person aus
       WRITE <fs_person>-stext.
     ENDLOOP.
   ENDLOOP
ENDLOOP.

Dieses Beispiel ist zugegebenermaßen etwas konstruiert, da es mittels eines Auswertungsweges deutlich einfacher wäre an die gewünschte Information zu kommen. Ein Beispiel mit Steuerungstabellen, z.B. welche Abwesenheitsart geht auf ein bestimmtes Abwesenheitskontingent, wäre an dieser Stelle aber zu komplex.

Der Vorteil dieser Technologie ist, dass verknüpfte Daten mit wenig ABAP-Code flexibel angesprochen werden können. Wenn verschiedene ähnliche Lesewege gefragt sind, muss man nicht für jeden Weg eine neue Routine verwenden.

Nicht zuletzt ist mit Meshes im Programm auch etwas transparenter, wie die einzelnen Sachverhalte miteinander zusammenhängen.

Definition eines Meshes

Meshes sind vereinfacht gesagt lediglich Strukturen, die Tabellen enthalten.
TYPES: BEGIN OF ty_struct,
        orgunit  TYPE p1001tab,
        position TYPE p1001tab,
        ...
     END OF ty_struct.
DATA: lm_orgunit_to_person TYPE ty_struct.

Mittels dieser Struktur können Sie ganz einfach auf die entsprechenden Tabellen zugreifen.


lm_orgunit_to_person-position
lm_orgunit_to_person-orgunit
READ TABLE lm_orgunit_to_person-position WITH KEY ...
LOOP AT lm_orgunit_to_person-orgunit INTO ...

Eine Mesh-Definition sieht der oben definierten Struktur sehr ähnlich, allerdings gelten einige Besonderheiten. Jede Tabelle in einem Mesh muss einen Primary Key haben, im Fall unserer Tabellen würde das folgendermaßen aussehen:

TYPES: ty_1001_tab TYPE SORTED TABLE OF lt_hrp1001 WITH NON-UNIQUE KEY plvar varyf,
       ty_1000_tab TYPE SORTED TABLE OF lt_hrp1000 WITH NON-UNIQUE KEY plvar objid otype,
"
BEGIN OF ty_struct,
          orgunit  TYPE ty_1001_tab,
          position TYPE ty_1001_tab,
          ...
END OF ty_struct.

Im nächsten Schritt erstellen wir anstatt einer Struktur ein Mesh:
TYPES: BEGIN OF MESH ty_mesh,
        orgunit TYPE ty_1001_tab,
        position TYPE ty_1001_tab,
        ...
END OF MESH ty_mesh.

Im Grunde genommen ist das schon ein gültiger Mesh. Der Vorteil eines Meshes ist aber die Verknüpfung dieser Tabellen.

TYPES: BEGIN OF MESH ty_mesh,
       orgunit TYPE ty_1001_tab
                ASSOCIATION _to_position TO position
                         ON otjid = varyf AND
                            plvar = plvar,
        position ty_1001_tab,
        ...
      END OF MESH ty_mesh.

Die nun hinzugefügte Assoziation mit dem Namen „_to_position“ verknüpft die Tabelle „orgunit“ mit der Tabelle „position“. Abgefragt werden zur Verknüpfung die Bedingungen, die nach der ON-Anweisung aufgelistet sind. Eine ärgerliche Einschränkung ist, dass keine Festwerte in die ON-Bedingung eingebaut werden können. Wäre es möglich zusätzlich noch OTYPE = ‚S‘ als Festwert hinzuzufügen, könnte der Mesh im Eingangsbeispiel auf die Tabellen HRP1000 und HRP1001 reduziert werden. Es gibt weitere Einschränkungen:

  • Es kann nur mittels AND verknüpft werden
  • Es kann nur auf Gleichheit (=) geprüft werden
  • Die Attribute die verglichen werden, müssen den gleichen Typ haben. Aus dem Grund wird als Tabellenschlüssel VARYF anstatt wie im Beispiel oben SOBID und SCLAS verwendet.

Für Assoziationen gilt außerdem:

  • Es können von jeder Tabelle beliebig viele Assoziationen auf andere Tabellen erstellt werden
  • Eine Assoziation kann auf die Tabelle verweisen, von der sie ausgeht

Mesh-Pfade

Der eben konstruierte Mesh kann nun folgendermaßen verwendet werden:

DATA: lm_mesh TYPE ty_mesh.
*
* Füllen mittels SELECT ...
*
"Lade eine Organisationseinheit
DATA(root) = lm_mesh-orgunit[ objid = '01234567' sobid = 'S' ].
"Lade die Planstelle, die zu der Verknüpfung gehört
"
" lm_mesh ist einfach eine Struktur, orgunit die Tabelle von der aus wir starten.
" Mittels \ sagen wir dem Programm, dass wir eine Assoziation ansprechen möchten.
" Danach kommt der Name der Assoziation. In eckigen Klammern wird eine Bedingung
" eingesetzt, dazu später mehr
"
DATA(ls_pos) = lm_mesh-orgunit\_to_position[ root ].

Im oberen Beispiel laden wir zunächst eine Verknüpfung von der Organisationseinheit zu einer Planstelle in die Struktur „root“. Anschließend greifen wir über die Struktur mesh auf die Tabelle orgunit zu und gehen über die Verknüpfung _to_position direkt auf die verknüpfte Planstelle. Es ist zwingend notwendig, dass in der ersten Tabelle ein „root“ definiert wird!

Beispiel

Wenn mehrere Tabellen und Assoziationen vorhanden sind, kann der Pfad beliebig verlängert werden. Mit dem jetzigen Wissen ist es möglich nochmal einen genaueren Blick auf das Eingangsbeispiel zu werfen. Der entsprechende Mesh sieht folgendermaßen aus:


TYPES: ty_hrp1001_tab TYPE SORTED TABLE OF hrp1001 WITH NON-UNIQUE KEY plvar varyf,
ty_hrp1000_tab TYPE SORTED TABLE OF hrp1000 WITH NON-UNIQUE KEY plvar objid otype.
TYPES: BEGIN OF MESH ty_o_to_cp,
        orgunit TYPE ty_hrp1001_tab
                ASSOCIATION to_position TO position
                         ON otjid = varyf AND
                            plvar = plvar,
        position TYPE ty_hrp1001_tab
                 ASSOCIATION to_person TO person
                          ON otjid = varyf AND
                             plvar = plvar,
        person TYPE ty_hrp1001_tab
               ASSOCIATION to_person1000 TO person1000
                        ON objid = objid AND
                           otype = otype AND
                           plvar = plvar,
        person1000 TYPE ty_hrp1000_tab,
      END OF MESH ty_o_to_cp.

Es gibt insgesamt fünf Tabellen und es gibt Assoziationen von der Organisationseinheit in Richtung zentraler Person, über die Planstelle und die Person. Wichtig ist bei diesem Beispiel natürlich, dass z.B. in die Tabelle „Positions“ nur Planstellen geladen werden.


LOOP AT lm_orgunit_to_cp-orgunit INTO root WHERE objid IN so_orgunits.
  LOOP AT lm_orgunit_to_cp-orgunit\to_position[ root ]\to_person[ ]\to_person1000[ WHERE objid IN so_objid ] INTO DATA(ls_hrp1000).
    WRITE / ls_hrp1000-objid.
  ENDLOOP.
ENDLOOP.

Im ersten Loop wird durch alle Organisationseinheiten gegangen. Dies ist nötig, da im Mesh, wie oben schon geschrieben, es genau einen Startknoten geben muss. Von der Organisationseinheit gehen wir über die Planstelle und die Person zur Zentralen Person in der HRP1001. Danach geht es mittels der Assoziation „to_cp_1000“ zu der Zentralen Person in der HRP1001. Die Eckigen Klammern dienen dazu die ausgewählten Objekte weiter einzuschränken, z.B. um Datumsbereiche zu selektieren. Die WHERE-Bedingung schränkt in diesem Beispiel ein, dass nur Personen mit einer Bestimmten ID verarbeitet werden. Diese Einschränkung bezieht sich auf die Tabelle „person“. Auch wenn keine Einschränkung angegeben wird, müssen die eckigen Klammern angegeben werden!

Gibt es evtl. ein Thema, was Sie „brennend“ interessiert und worüber wir unbedingt schreiben sollten?

Dann schicken Sie uns Ihre Idee gerne per Mail über das folgende Kontaktformular! Vielen Dank im Voraus!