HANA SQLScript Transformationsroutinen im BW/4HANA – ein Beispiel

In diesem Blogpost möchte ich ein kleines Beispiel für eine AMDP [aka. HANA Script oder AMDP Script [1]Es gibt eigentlich kein HANA Script oder AMDP Script. Diese Begriffe findet man nur in der SAP BW Oberfläche bei den Transformationen. Diese Wortschöpfung ist eine Mischung aus den Begriffen HANA bzw. AMDP und SQLScript. Korrekt müsste es heißen: AMDP Transformationsroutinen oder SQLScript Transformationsroutinen ] Transformationsroutine im SAP BW/4HANA zeigen. Dabei beginne ich mit den Begriffen AMDP und SQLScript, zeige dann, welchen Code das System als Hülle für unsere Implementierung erzeugt und fülle diese dann mit einer einfachen SQLScript-Logik zur Berechnung von laufenden Summen.

In dem Quell-ADSO habe ich pro Werttyp (VALTYP) , Konto (ACCOUNT) und Tag (BUDAT) einen Betrag (AMOUNT). Jetzt möchte ich diese Beträge in dem Feld TOTAL über die Zeit aufaddieren.

Feldmapping in der Transformation

SQLScript (nicht HANA Script oder AMDP Script!)

Die HANA Datenbank versteht, wie jede andere relationale Datenbank auch, die Standard-Abfragesprache SQL. Und wie die meisten anderen Datenbankhersteller hat auch die SAP den SQL-Standard um ein paar nette Features erweitert. In erster Linie geht es bei diesen Erweiterungen darum, dass man auch auf der Seite des DB-Servers längere Programme schreiben kann, die dann vollständig dort ausgeführt werden. Diese Programme werden in sogenannten Prozeduren gespeichert.

AMDP

AMDP steht für ABAP Managed Database Procedures. Das heist übersetzt: Prozeduren die vom ABAP verwaltet werden. Mittlerweile geht das AMDP Framework weit über diese Beschreibung hinaus, denn es können damit nicht nur Prozeduren angelegt werden. Auch CDS-Table Functions oder Skalare– bzw. Tabellenfunktionen lassen sich damit anlegen.

Um die Details von AMDP brauchen wir uns zunächst keine Gedanken zu machen. Es reicht zu wissen: Das SAP BW generiert uns den Rahmen als ABAP Klasse, in dem wir dann eine Methode in SQLScript implementieren müssen.

Die AMDP bzw. SQLScript Transformationsroutinen

Wenn wir im BW/4HANA eine Routine anlegen, stellt sich zunächst die Frage, in welcher Sprache diese Routine implementiert werden soll. Das hängt von der eingestellten Laufzeitumgebung ab. Hier ist die SAP-HANA-Laufzeit der Standard. Wenn wir das nicht verändern, dann müssen unsere Routinen in SQLScript implementiert werden:

Auswahl der Laufzeitumgebung in Transformationen
Auswahl der Laufzeitumgebung in Transformationen

Um eine Routine anzulegen klickt man auf den entsprechenden Button, siehe Abbildung. Bei den Endroutinen hat man die Möglichkeit, dabei auch gleich die Laufzeit auf ABAP umzustellen [2]Warum das nur bei den Endroutinen möglich ist, bleibt mir ein Rätsel. . Für das Beispiel klicke ich auf den Button für die Endroutinen „SAP HANA-Script anlegen“.

Buttons zum Anlegen von Routinen

Dann erscheint das Popup für die Auswahl der Felder, siehe Abbildung. Standardmässig sind alle in der Transformation zugeordneten Felder angekreuzt. Das Feld TOTAL möchte ich in diesem Beispiel berechnen und kreuze es deshalb ebenfalls an, bevor ich auf den Button Routine bearbeiten klicke.

Auswahl der Felder für die Endroutine

Daraufhin geht in Eclipse ein neuer Tabreiter auf mit einer generierten ABAP Klasse im /BIC/-Namensraum. Der Klassenname enthält das Ende der Transformations ID (TRANID). In dieser ABAP Klasse gibt es eine Methode GLOBAL_END, die wir in SQLScript implementieren können[3]Bei mir ist der Hintergrund für Embedded Languages in Gelb eingefärbt. Wie das geht, lernen Sie in dieser kostenlosen Probelektion aus meinen E-Learning Kursen. :

Screenshot der Methode GLOBAL_END

Diese Klassen können wir nicht ohne Weiteres aktivieren. Dafür müssen wir zunächst etwas Code einfügen, da der Parameter OUTTAB zugewiesen sein muss.

INTAB und OUTTAB

Was früher der Parameter RESULT_PACKAGE war, teilt sich in AMDP Transformationsroutinen in die beiden Parameter INTAB und OUTTAB auf. Bei Start- und Endroutinen haben beide die gleiche Struktur. D.h. wir kommen mit der folgenden Minimalimplementierung aus, die ja auch im Kommentar vorgeschlagen wird:

outTab = SELECT * FROM :inTab;

Leider macht diese Implementierung nichts, als eine 1:1 Zuweisung. Die einfachste sinnvolle Implementierung basiert immer auf einer vollständigen Feldliste. Sie sieht also in unserem Fall so aus:

  outtab = SELECT budat,
                  valtype,
                  account,
                  recordmode,
                  amount,
                  total,
                  curr,
                  record,
                  sql__procedure__source__record
             FROM :intab;

Dieser Quellcode macht ebenfalls nur eine 1:1 Zuweisung. Aber hier können wir jetzt gezielt die einzelnen Felder bearbeiten. In unserem Falle wollen wir das Feld TOTAL berechnen. In ABAP würden wir hierzu die Daten nach ACCOUNT, VALTYPE und BUDAT sortieren und in einer Schleife die Werte addieren. Das geht in SQLScript wesentlich leichter – mit Window Functions[4]SAP Dokumentation zu Window Functions. Damit kann ich ganz einfach eine laufende Summe berechnen lassen:

SUM(amount) OVER (PARTITION BY account, valtype ORDER BY budat ASC) AS total

Damit sieht die gesamte Methode dann so aus:

METHOD GLOBAL_END BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY.
-- *** Begin of routine - insert your code only below this line ***

-- Note the _M class are not considered for DTP execution.
-- AMDP Breakpoints must be set in the _A class instead.

  outtab = SELECT budat,
                  valtype,
                  account,
                  recordmode,
                  amount,
                  SUM(amount) OVER (PARTITION BY account, valtype ORDER BY budat ASC) AS total,
                  curr,
                  record,
                  sql__procedure__source__record
             FROM :intab;

-- *** End of routine - insert your code only before this line ***
ENDMETHOD.

ERRORTAB

Der Parameter ERRORTAB spielt zum Einstieg keine Rolle. Er ist, wie der Name schon andeutet, für die Fehlerverarbeitung zuständig. In BW/4HANA Systemen ist er nur dann vorhanden, wenn in der Transformation die Checkbox „Fehlerbehebung für HANA-Routinen zulassen“ angekreuzt ist. Falls er da ist, muss er aber zugewiesen sein, weshalb er immer wieder für Ärger sorgt. Wenn wir wegen der ERRORTAB eine Fehlermeldung bekommen, können wir einfach diesen sinnfreien Code am Ende der Routine einfügen, dann ist das System glücklich:

errorTab = SELECT * FROM :errorTab;

Fazit

Der Aufwand für eine AMDP Transformationsroutine ist nicht größer, als der für eine ABAP Routine. Wenn man etwas Erfahrungen in dem Thema hat, dann geht es sogar erheblich schneller und eleganter. Der Schlüssel zum Erfolg ist das Know-How in SQLScript. Die Grundlagen hiervon muss man kennen, sonst tut man sich schwer, gute Lösungen zu finden. Deshalb empfehle ich jedem, die Schulungen von Brandeis Consulting. Entweder als Live Training, Inhouse oder als offene Schulung. Oder die E-Learning Kurse SQLScript Grundlagen und AMDP Transformationsroutinen. Es gibt auch ein paar kostenlose Probelektionen, wo sie ein paar hilfreiche Tipps mitnehmen können.

Anmerkungen und Verweise

Anmerkungen und Verweise
1 Es gibt eigentlich kein HANA Script oder AMDP Script. Diese Begriffe findet man nur in der SAP BW Oberfläche bei den Transformationen. Diese Wortschöpfung ist eine Mischung aus den Begriffen HANA bzw. AMDP und SQLScript. Korrekt müsste es heißen: AMDP Transformationsroutinen oder SQLScript Transformationsroutinen
2 Warum das nur bei den Endroutinen möglich ist, bleibt mir ein Rätsel.
3 Bei mir ist der Hintergrund für Embedded Languages in Gelb eingefärbt. Wie das geht, lernen Sie in dieser kostenlosen Probelektion aus meinen E-Learning Kursen.
4 SAP Dokumentation zu Window Functions