CubeServ Blog
Bleiben Sie auf dem neuesten Stand, rund um das Data Driven Business mit Tools für Analytics von SAP & Co. und verpassen Sie keine Neuigkeiten, Downloads & Veranstaltungen.

SQLscript Lösungsmuster

Lange danach gesucht? Jetzt gefunden!

Unsere Übersicht von typischen Problemen und Lösungen im Bereich von HANA SQLscript. 

Die Lösungsmuster reichen dabei von rein sprachlichen Problemen (z.B. „mit welchem Sprachelement ermittle ich den ersten Eintrag“) über formale Probleme (z.B. „wie wandle ich in SQLscript Zeitmerkmale um“) bis zu applikatorischen Anforderungen (z.B. „wie lese ich in SQLscript Stammdaten nach“).

Die Lösungsmuster erheben nicht den Anspruch, die alleinige oder beste Lösung eines Problems zu sein, sondern sollen als Kopiervorlage dienen und Sie mit verschiedenen Lösungsansätzen inspirieren. Ihr Feedback zu Verbesserungen, Alternativen und Ergänzungen ist jederzeit willkommen!

Das Coding-Beispiel ist so formuliert, wie es typischerweise in einer AMDP-Routine vorkommen könnte. Diese Formulierung kann allerdings in einem HANA-Studio-SQL-Fenster oder im SQL-Editor der ABAP-Transaktion DBACOCKPIT nicht verwendet werden (da dort nicht definiert ist, was die inTab sein soll). Es ist daher an einigen Stellen auch ein Coding-Beispiel angegeben, das man im SQL-Fenster verwendet könnte. In diesen Beispielen sind zusätzliche Zeilen, die die Beispieldaten aufbauen.

Initialwerte

Beschreibung

Zeichenartige Spalten mit “ initalisieren, Nummern mit 0.

Coding Beispiel

outtab =
SELECT
'' AS "/BIC/STRASSE",
0  AS "/BIC/HAUSNR"
FROM :intab; 

Eine ähnliche Formulierung erzeugt Beispieldaten, die dann weiterverwendet werden können.

Coding Beispiel SQL-Editor

SELECT 'A' AS "SPALTE_A",
       'B' AS "SPALTE_B", 
       1.5 AS "BETRAG" 
     FROM DUMMY; 

Temporäre Tabellen (Tabellenvariablen)

Beschreibung

Tabellen werden dynamisch zur Laufzeit definiert, wenn sie mit einem Select gefüllt werden.

Anmerkung

Tabellenvariablen müssen nicht vor der Benutzung deklariert werden. In der weiteren Verwendung muss dem Namen aber ein „:“ vorangestellt werden.

Coding Beispiel

tmptab  = SELECT * FROM :intab;
tmptab2 = SELECT * FROM :tmptab;
outtab  = SELECT * from :tmptab2;
 

Tabellenvariablen sind ein Beispiel dafür, wo sich SQL von SQLscript unterscheidet. Diese Variablen sind Teil der SQLscript-Sprache, aber nicht der SQL-Sprache.

Um sie daher in einem SQL-Fenster verwendet zu können, muss ein sogenannten anonymer Block eingefügt werden. 

Das letzte SELECT in folgendem Beispiel erzeugt dann die Ausgabe des Resultats des SQL-Fensters. Ohne diese Zeile wird das Statement zwar ausgeführt, es gibt aber kein Ergebnis. Mehrere solcher SELECTs am Ende erzeugen auch mehrere Resultats-Fenster im SQL-Editor des HANA Studios.

Coding Beispiel SQL-Fenster

DO
BEGIN
tmptab = SELECT 'A' AS "SPALTE_A", 
                'B' AS "SPALTE_B", 
                1.5 AS "BETRAG" 
            FROM DUMMY;
tmptab2 = SELECT "SPALTE_A" FROM :tmptab;
SELECT * FROM :tmptab2; -- Tabelle als Resultat ausgeben
END; 

Umbenennen von Spalten

Beschreibung

Eine oder mehrere Spalten soll einen anderen Namen erhalten.

Coding Beispiel

outtab = 
  SELECT "ALTER_SPALTENNAME" AS "NEUER_SPALTENNAME" FROM :inTab; 

Coding Beispiel SQL-Fenster

DO
BEGIN
tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY;
SELECT * FROM :tab1; -- Resultat Tabelle mit SPALTE_A
SELECT "SPALTE_A" AS "NEUE_SPALTE" FROM :tab1; -- Resultat umbenannt
END; 

Vereinigung zweier strukturgleicher Tabellen

Beschreibung

Es wird die Vereinigungsmenge zweier Tabellen gebildet. Die Tabellen müssen dabei von identischer Struktur sein.

Coding Beispiel

outtab = 
  SELECT columns FROM :TAB1
  
  UNION ALL
  
  SELECT columns FROM :TAB2; 

Coding Beispiel SQL-Fenster

DO
BEGIN
tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY;
tab2 = SELECT * FROM :tab1; -- 2. Tabelle mit Daten
tab3 = SELECT * FROM :tab1 
       UNION ALL 
       SELECT * FROM :tab2;
SELECT * FROM :tab3; -- Resultat ausgeben
END; 

Join zweier Tabellen

Beschreibung

Es wird der Join zweier Tabellen gebildet. 

Coding Beispiel

outtab = 
  SELECT T1.*, T2.* FROM :TAB1 AS T1
    LEFT OUTER JOIN :TAB2 AS T2
    ON T1.SPALTE_A = T2.SPALTE_X AND
       T1.SPALTE_B = T2.SPALTE_Y;
   

Coding Beispiel SQL-Fenster

DO
BEGIN
tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY;
tab2 = SELECT 'A' AS "SPALTE_X", 
              'C' AS "SPALTE_Y", 
              2 AS "MENGE" 
             FROM DUMMY;
tab3 = SELECT T1.*, T2.* from :tab1 AS T1
         LEFT OUTER JOIN :tab2 AS T2
         ON T1."SPALTE_A" = T2."SPALTE_X";
SELECT * FROM :tab3; -- Resultat ausgeben
END; 

Fallunterscheidung

Beschreibung

Sie können bereits im SELECT-Statement in der zu ermittelnden Spalte eine Fallunterscheidung machen mit Hilfe von CASE.

Coding Beispiel

outtab = 
SELECT
CASE BUCHUNGSART
  WHEN 'HABEN' THEN BETRAG
  WHEN 'SOLL'  THEN -1 * BETRAG
  ELSE 0 
END AS BETRAG_VZ
FROM :intab; 

Dieses Statement ist gleichwertig zu folgender Version:

outtab = 
SELECT
CASE 
  WHEN BUCHUNGSART = 'HABEN' THEN BETRAG
  WHEN BUCHUNGSART = 'SOLL'  THEN -1 * BETRAG
  ELSE 0 
END AS BETRAG_VZ
FROM :intab; 

In der 2. Formulierung hat man mehr Freiheit, in der WHEN-Bedingung auch komplexere Bedingungen zu formulieren, z.B.:

outtab = 
SELECT
CASE 
  WHEN BUCHUNGSART = 'HABEN' AND 
       NOT ( STORNOFLAG = 'X' )
       THEN BETRAG
  WHEN BUCHUNGSART = 'HABEN' AND 
       STORNOFLAG = 'X'
       THEN 0
  WHEN BUCHUNGSART = 'SOLL'  THEN -1 * BETRAG
  ELSE 0 
END AS BETRAG_VZ
FROM :intab; 

Coding Beispiel SQL-Fenster

DO
BEGIN
tab1 = SELECT 'HABEN' AS "BUCHUNGSART", 1.5 AS "BETRAG" FROM DUMMY
       UNION ALL
       SELECT 'SOLL'  AS "BUCHUNGSART", 2.5 AS "BETRAG" FROM DUMMY;
tab2 = SELECT "BUCHUNGSART", "BETRAG",
       CASE 
         WHEN "BUCHUNGSART" = 'HABEN' THEN "BETRAG"
         WHEN "BUCHUNGSART" = 'SOLL'  THEN -1 * "BETRAG"
         ELSE 0
       END AS "BETRAG_VZ"
      FROM :tab1;
SELECT * FROM :tab2; -- Resultat ausgeben
END; 

Variable definieren, befüllen und benutzen

Beschreibung

Sie können lokale Variablen definieren. Diese lassen sich einerseits mit SELECT-Statements befüllen, andererseits kann ihr Inhalt auch wieder per SELECT ausgelesen werden oder sie können in CASE-Anweisungen verwendet werden.

Coding Beispiel

DECLARE lv_tvarvc STRING;

SELECT DISTINCT LOW INTO lv_tvarvc
  FROM "TVARVC" 
  WHERE "NAME" = 'my_setting';
  
outtab = 
  SELECT :lv_tvarvc AS TVARVC, * FROM intab; 

Coding Beispiel SQL-Fenster

DO
BEGIN
DECLARE lv_tvarvc STRING;
tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY;
SELECT 'Value1' INTO lv_tvarvc FROM DUMMY;
SELECT :lv_tvarvc, * FROM :tab1; -- Resultat ausgeben
END; 

NULL-Werte vermeiden

Beschreibung

Werden z.B. in einem Left-Outer-Join in der verjointen Tabelle keine passenden Treffer gefunden, so enthalten die selektierten Spalten dieser Tabelle als Ergebnisse NULL-Werte. Diese Werte sind recht unangenehm, z.B. weil sie im ABAP auch keinem Initialwert entsprechen. Daher sollten solche NULL-Werte immer mit der Funktion COALESCE abgefangen werden. COALESCE(A,B) gibt den Wert A zurück, wenn A nicht NULL ist, ansonsten B. Somit kann man mit B immer einen Ersatzwert angeben, der anstelle von NULL zurückgegeben werden soll.

Alternativ kann man auch mit der Funktion IFNULL arbeiten.

Anmerkung

Ein Codingbeispiel findet sich im Abschnitt Datumsrechnung.

Anzahl Zeilen zählen

Beschreibung

Sie können mit Hilfe des COUNT-Operators die Zeilen zählen lassen. Sie können aber auch ermitteln, wie oft Merkmale jeweils vorkommen, ob z.B. nur einmal oder auch mehrfach.

Hier geben wir nur ein Beispiel für die SQL-Konsole an, die Syntax ist dann leicht auf Anwendungsfälle im AMDP übertragbar.

Coding Beispiel SQL-Fenster

DO
BEGIN
DECLARE lv_anz_zeilen INT;
tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY
       UNION
       SELECT 'A' AS "SPALTE_A", 
              'C' AS "SPALTE_B", 
              2.5 AS "BETRAG"
            FROM DUMMY;
               
SELECT COUNT( * ) INTO lv_anz_zeilen FROM :tab1; -- Gesamtzahl als
                                                 -- lokale Variable

tab2 = SELECT COUNT ( * ) AS "COUNTER" FROM :tab1; -- Gesamtzahl als Tabelle

SELECT :lv_anz_zeilen AS "Gesamtzahl", 
       COUNT(*) AS "Anzahl pro Merkmal SPALTE_A", 
       "SPALTE_A" FROM :tab1
  GROUP BY "SPALTE_A";  -- Ausgabe 1, auch wieviele Ausprägungen SPALTE_A
  
SELECT * from :tab2;  -- Ausgabe 2
              
END; 

Bedingungen

Beschreibung

Mit Hilfe von IF können Bedingungen formuliert werden. 

Anmerkung

Überraschend häufig lassen sich IF-Statements durch CASE-Anweisungen im SELECT ersetzen. Diese passen besser dazu, die Daten immer massenweise zu prozessieren. Durch IF werden gerne wieder Einzelfälle betrachtet, was man vermeiden sollte, um gute Performanz zu erhalten. 

Coding Beispiel

DO
BEGIN
DECLARE lv_anz_zeilen INT;
tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY
       UNION
       SELECT 'A' AS "SPALTE_A", 
              'C' AS "SPALTE_B", 
              2.5 AS "BETRAG"
            FROM DUMMY;
               
SELECT COUNT( * ) INTO lv_anz_zeilen FROM :tab1; -- Gesamtzahl

IF :lv_anz_zeilen > 0 THEN

  SELECT 'Tabelle ist nicht leer' AS "TEXT" from DUMMY;

ELSE

  SELECT 'Tabelle ist leer' AS "TEXT" from DUMMY;
              
END IF;

END; 

Summe, Max, Min, ...

Beschreibung

Aggregationen wie Summenbildung, Maximum einer Spalte o.ä. können wieder direkt im SELECT-Statement gebildet werden. 

Anmerkung

Die Spalten, über die hinweg die Aggregatsfunktion gebildet wird, müssen in einer GROUP-BY-Klausel stehen. I.a. sind das also alle Spalten ausser denen, auf denen die Summe, das Maximun o.ä. gebildet werden soll.

Coding Beispiel

DO
BEGIN

tab1 = SELECT 'A' AS "SPALTE_A", 
              'B' AS "SPALTE_B", 
              1.5 AS "BETRAG" 
             FROM DUMMY
       UNION
       SELECT 'A' AS "SPALTE_A", 
              'C' AS "SPALTE_B", 
              2.5 AS "BETRAG"
            FROM DUMMY;
               
               
SELECT "SPALTE_A", MAX( "BETRAG" ) AS MAX FROM :tab1
  GROUP BY "SPALTE_A"; -- Max pro Ausprägung SPALTE_A

SELECT "SPALTE_B", MAX( "BETRAG" ) AS MAX FROM :tab1
  GROUP BY "SPALTE_B"; -- Max pro Ausprägung SPALTE_B

END; 

Führende 0en ersetzen

Beschreibung

Mit Hilfe des LTRIM-Operators können führende 0en ersetzt werden. 

Anmerkung

Der LTRIM-Operator kann auch eingesetzt werden, um z.B. führende Leerzeichen zu eliminieren.

Coding Beispiel

SELECT LTRIM( BPARTNER, '0') AS BP FROM :intab; 

Coding Beispiel SQL-Fenster

SELECT LTRIM( '00001234', '0') AS BP FROM DUMMY; 

Prüfung auf Ziffern

Beschreibung

Sie können Spalten daraufhin prüfen, ob nur Ziffern in ihnen vorkommen (z.B. Datumsfelder im internen ABAP-Format). 

Anmerkung

Im Beispiel werden die Datensätze selektiert und markiert, die etwas enthalten, das keine Ziffer ist.

Coding Beispiel

SELECT DATUM, 'X' AS MARKIERUNG FROM :intab
  WHERE DATUM LIKE_REGEXPR '[^0-9]'; 

Verdichten von Leerzeichen

Beschreibung

Sie können führende, schliessende, aber auch mittige Leerzeichen entfernen lassen durch Verwendung des sehr mächtigen Operators REPLACE_REGEX. 

Coding Beispiel

SELECT REPLACE_REGEXPR ('[\s]' in 'ABC DEF') FROM DUMMY; 

Entfernen ungültiger Zeichen

Beschreibung

Sie können für das BW ungültige Zeichen entfernen lassen durch Verwendung des sehr mächtigen Operators REPLACE_REGEX in Kombination mit einem Ausdruck, der alle nicht druckbaren Zeichen aus einem Text entfernt. 

Die erste Coding-Variante entfernt alle nicht-druckbaren Zeichen, zu denen leider aber auch z.B. die deutschen Umlaute zählen. Falls das nicht gewünscht ist, entfernt die zweite Variante nur gewisse unsichtbare Steuerzeichen plus das Zeichen für geschütztes Leerzeichen (Hex A0).

Coding Beispiel

SELECT REPLACE_REGEXPR( '([^[:print:]])' IN 'TEXT' WITH '' OCCURRENCE ALL ) FROM DUMMY;

SELECT REPLACE_REGEXPR( '([[:cntrl:]\x{00A0}])' IN 'TEXT' WITH '' OCCURRENCE ALL ) FROM DUMMY; 

Ersten Datensatz ermitteln

Beschreibung

Mit Hilfe von MAX- oder MIN-Funktionen lassen sich neueste oder älteste Datümer ermitteln. Man kann aber auch den ersten Datensatz einer bestimmten Reihe ermitteln, z.B. den BusinessPartner mit frühestem Änderungsdatum.

Anmerkung

Analog kann man natürlich auch den letzten Datensatz ermitteln mit LAST_VALUE.

Coding Beispiel

SELECT FIRST_VALUE( BPARTNER ORDER BY CHANGED_ON ) FROM :intab;

SELECT BPARTNER, LAST_VALUE ( AMOUNT ORDER BY CHANGED_ON ) AS AMOUNT FROM :intab 
  GROUP BY BPARTNER; 

Rang ermitteln

Beschreibung

Sie können mit Hilfe der RANK-Funktion Daten eine Rangnummer zuweisen. Dies ist eine Art Sortiernummer, hat aber den Vorteil, dass die Daten dazu nicht sortiert oder umsortiert werden müssen.

Anmerkung

Das kann man z.B. dazu verwenden, um die letzte Position zu einem Beleg zu ermitteln. 

Coding Beispiel

tab1 = SELECT *, 
         RANK() OVER ( PARTITION BY intab."BELEGNUMMER" ORDER BY intab."POSITION" DESC ) 
         AS ZEILENNUMMER_ABSTEIGEND 
         FROM :intab;
         
tab2 = select * from :tab1
         where ZEILENNUMMER_ABSTEIGEND = 1; 

Zugriff auf vorherige oder nachfolgende Zeilen

Beschreibung

Wenn Sie jeweils Zeilen einer Tabelle mit der vorherigen oder nachfolgenden Zeile vergleichen wollen, führt das gerne dazu, dass man einen Cursor öffnet und eine Schleife programmiert. Das ist prinzipiell möglich, aber es widerspricht dem Paradigma, die Daten möglichst massenhaft zu prozessieren, um optimale Performanz zu erhalten. 

Eine Möglichkeit wäre, die Tabelle mit sich selbst um eine Zeile versetzt zu verjoinen, damit wäre ein Vergleich innerhalb einer (dann doppelt so breiten) Zeile möglich.

HANA SQLscript bietet aber mit den LEAD- und LAG-Funktionen eine Möglichkeit, auf die entsprechenden Zeilen zuzugreifen.

Anmerkung

Das Beispiel listet die Mandanten eines Systems. In der ersten Spalte die normale Auflistung, in der zweiten wird mit Lead auf die nächste Zeile der Tabelle vorgegriffen, mit Lag auf die vorherige zurückgegriffen.

Coding Beispiel

select MANDT, 
       LEAD( MANDT ) OVER ( ORDER BY MANDT ) AS LEAD, 
       LAG( MANDT )  OVER ( ORDER BY MANDT ) AS LAG 
  FROM T000;
  

Ergebnis

Datumsrechnung

Beschreibung

Aus Kalendertag sollen die anderen Merkmale (Woche, Monat, Jahr,…) hergeleitet werden.

Anmerkung

In der HANA müssen einmalig die Zeittabellen gefüllt werden (→ Modeler Perspektive), sonst sind die Tabellen leer. 
Alternativ können die Tabellen auch mit MDX-Kommandos wie
MDX UPDATE TIME DIMENSION … oder MDX UPDATE FISCAL CALENDAR …
befüllt werden. Dabei darauf achten, was die feinste Granularität sein soll (z.B. Tag oder Sekunde).
Wird nichts gefunden, wird auf den 01.01.2020 zurückgefallen (das war ein Mittwoch, Weekday = 3, daher dieser Wert).

Coding Beispiel

-- UDATE bitte durch das entsprechende Zeitmerkmal ersetzen

SELECT

  COALESCE( I.UDATE, '20200101' ) AS CALDAY,

  COALESCE( TO_NVARCHAR( T.DAY_OF_WEEK_INT + 1 ), '3' ) AS WEEKDAY1,

  COALESCE( T.CALMONTH, '01' ) AS CALMONTH,

  COALESCE( T.CALWEEK, '202001' ) AS CALWEEK,

  COALESCE( T.MONTH, '01' ) AS CALMONTH2,

  COALESCE( T.CALQUARTER, '20201' ) AS CALQUARTER,

  COALESCE( TO_NVARCHAR( T.QUARTER_INT ), '1' ) AS CALQUART1,

  CASE 
    WHEN COALESCE( T.QUARTER_INT, 1 ) = 1 OR 
         COALESCE( T.QUARTER_INT, 1 ) = 2 THEN
      '1'
    ELSE
      '2'
  END AS HALFYEAR1,

  COALESCE( T.YEAR, '2020' ) AS CALYEAR,

FROM :intab AS I

LEFT OUTER JOIN "_SYS_BI"."M_TIME_DIMENSION" AS T

    ON I.UDATE = T.DATE_SAP; 

Herleitung eines aktuellen UTC-Zeitstempels

Beschreibung

In einer AMDP-Routine soll der aktuelle UTC-Zeitstempel ermittelt werden.

Anmerkung

Beispielcoding für eine AMDP-Feldprozedur.

Coding Beispiel

METHOD PROCEDURE BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY.

outtab =
SELECT to_nvarchar(current_utctimestamp, 'YYYYMMDDHH24MISS') AS "ETL_TIMESTAMP",
record,
sql__procedure__source__record
FROM :intab;

errortab =
SELECT '' AS "ERROR_TEXT" ,
'' AS "SQL__PROCEDURE__SOURCE__RECORD"
FROM dummy
WHERE 0 = 1;

ENDMETHOD. 

Herleitung der Request-TSN

Beschreibung

In BW on HANA gibt die AMDP-Schnittstelle die Request-Nummer nicht her. Sie muss etwas mühsam hergeleitet werden, um z.B. in einem Corporate Memory diese Nummer ablegen zu können (empfohlen, da man einzelne Requests zurückladen möchte und dieses Feld im Standard nicht als Selektion im DTP zur Verfügung steht).

Anmerkung

Beispiel AMDP-Feldroutine.
Es muss jeweils das Ziel-ADSO im Coding angegeben werden.

Coding Beispiel

METHOD PROCEDURE BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT 
OPTIONS READ-ONLY using RSPMREQUEST.


declare lv_reqtsn varchar(23);

SELECT request_tsn INTO lv_reqtsn FROM rspmrequest
where datatarget = '' AND
request_status = 'Y' AND
last_operation_type = 'C' AND
request_is_in_process = 'Y' AND
storage = 'AQ';

outtab =
SELECT lv_reqtsn AS "ETL_REQTSN",
record,
sql__procedure__source__record

FROM :inTab as input;

errortab =
SELECT '' AS "ERROR_TEXT" ,
'' AS "SQL__PROCEDURE__SOURCE__RECORD"
FROM dummy
WHERE 0 = 1;

ENDMETHOD. 

Aktuellste Daten eines wo-ADSOs

Beschreibung

Wenn Sie Daten aus einem schreiboptimierten ADSO lesen (wo-ADSO), geht es häufig dazu, den neuesten Stand dieser Daten zu lesen, also den neuesten Request. Dies geht ganz einfach durch Suche nach der maximalen Request-Nummer.

Coding Beispiel

SELECT T1.REQTSN, T1.KEY, T1.FIELD
  FROM WO-ADSO as T1
    JOIN ( SELECT MAX(REQTSN) as TSN, KEY FROM WO-ADSO GROUP BY KEY ) AS T2 
    ON T1.REQTSN = T2.TSN AND
       T1.KEY = T2.KEY
  WHERE T1.KEY = ...;
 

Nachlesen von Stammdaten

Beschreibung

Sie können Stammdaten eines InfoObjekts auslesen, indem Sie die P-Tabelle (bei zeitabhängigen Stammdaten die Q-Tabelle) des InfoObjekts hinzujoinen. 

Anmerkung

Ist referentielle Integrität gegeben (d.h. existieren garantiert Stammdaten zu den Bewegungsdaten), dann kann ein INNER JOIN verwendet werden. Dieser ist performanter als ein OUTER JOIN. 
Ansonsten verwendet man einen LEFT OUTER JOIN, und sollte das eventuell Auftreten von NULL-Werten durch COALESCE abfangen.

Coding Beispiel

SELECT T1.*,
       COALESECE( T2.FIELD, '') AS FIELD
  FROM ADSO as T1
    LEFT OUTER JOIN /BIC/POBJECT AS T2
    ON T2.KEY = T1.OBJECTFIELD
  WHERE T2.OBJVERS = 'A' AND ...;
 

Im AMDP SQL-Fehler abfangen

Beschreibung

Treten im AMDP SQL-Fehler auf, so können diese abgefangen und als Fehlermeldungen an den DTP zurückgegeben werden.

Anmerkung

Das folgende Coding sollte dann an den Anfang des AMDP-Scripts gestellt werden.

Coding Beispiel

DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN 
  outtab = SELECT TOP 0 * from :outtab;
  errortab = SELECT 'My Error Message' AS ERROR_TEXT, 
                    '' AS SQL__PROCEDURE__SOURCE__RECORD FROM DUMMY'; 
END;
 

Im AMDP eigene SQL-Fehlermeldungen werfen

Beschreibung

Man kann auch eigene Fehlermeldungen werfen, die dann sowohl im Protokoll des DTPs als auch als SQL-Fehlermeldungen in den Tracefiles des Indexservers der HANA-DB auftauchen. 

Anmerkung

Das folgende Coding sollte dann an den Anfang des AMDP-Scripts gestellt werden.

Coding Beispiel

DECLARE MYCOND CONDITION FOR SQL_ERROR_CODE 10001;
DECLARE EXIT HANDLER FOR MYCOND RESIGNAL;
SIGNAL MYCOND SET MESSAGE_TEXT = '     Typical Not-found Error';
   


-- in case of error throw here
SIGNAL MYCOND;
 

Im AMDP gültige Sätze verbuchen, fehlerhafte in Errorstack schreiben

Beschreibung

Ist man in einem BW/4HANA-Release, so muss man als Voraussetzung muss man in der Transformation die Einstellung „Fehlerhandling für HANA-Routinen erlauben“. Ist dies gesetzt, so definiert die AMDP-Schnittstelle neben der outTab-Tabelle auch eine errorTab-Tabelle.
Im DTP muss zusätzlich eine geeignete Einstellung vorgenommen sein, z.B. die Einstellung „Request auf grün setzen, Fehlerstack schreiben, gültige Sätze verbuchen“. 

Anmerkung

Das folgende Coding zeigt beispielhaft, wie aus einer Stammdatentabelle Sätze nachgelesen werden. Diejenigen Sätze, bei denen ein nicht-leerer Eintrag gefunden wird, werden als gültige Sätze behandelt, die anderen werden als fehlerhafte Sätze behandelt. 

Coding Beispiel

table1 = SELECT
       :i_req_requid as ZTS1REQTSN, 
       CALYEAR,
       COUNTRY,
       PRODUCT,
       I.RECORDMODE,
       I."/BIC/ZTS1CNTRY",
       COALESCE(P."/BIC/ZTS1FAREA",'') AS "/BIC/ZTS1FAREA",
       to_nvarchar(current_utctimestamp, 'YYYYMMDDHH24MISS') AS UTC,
       QUANTITY,
       RECORD,
       SQL__PROCEDURE__SOURCE__RECORD

   FROM :inTab as I
   LEFT OUTER JOIN "/BIC/PZTS1CNTRY" AS P
   ON I."/BIC/ZTS1CNTRY" = P."/BIC/ZTS1CNTRY" AND
      P.OBJVERS = 'A' AND
      NOT ( P.RECORDMODE = 'R' );

-- Allow Error Handling for HANA Routines is enabled

if :i_error_handling = 'TRUE' then
   errorTab = select
              'FAREAMISSING' as ERROR_TEXT,
              SQL__PROCEDURE__SOURCE__RECORD as SQL__PROCEDURE__SOURCE__RECORD
              FROM :table1
              where "/BIC/ZTS1FAREA" = '';

end if;
   
outTab = select * from :table1
            where NOT ( "/BIC/ZTS1FAREA" = '' );
 
Newsletter abonnieren

Bleiben Sie auf dem neuesten Stand, rund um das Data Driven Business mit Tools für Analytics von SAP & Co. und verpassen Sie keine Neuigkeiten, Downloads & Veranstaltungen. 

Autor
Expert Team

Blog Artikel unserer Experten

Berechtigungen in Power BI – im Zusammenspiel mit SAP BW

Zeit der Veränderungen Steigende Zinsen, neue regulatorische Anforderungen, Probleme in den Lieferketten – mehr denn je stehen Unternehmen vor der Herausforderung die Auswirkungen neuer Situationen rasch einschätzen und bei Bedarf entsprechende Maßnahmen einleiten zu können. Vor diesem Hintergrund wird die IT-Infrastruktur vielerorts neu gedacht bzw.

circular-barplot-with-groups

Advanced Analytics mit SAP und R

Warum sich mit der SAP R-Integration beschäftigen? Die überwiegende Mehrheit der Unternehmen nutzt fortschrittliche Analysen mit R- und SAP-Tools, um zukünftige Ereignisse zu prognostizieren und datengestützte, fundierte Entscheidungen zu treffen. Mit diesem Blogbeitrag zeige ich die Vorteile und wesentlich Zusammenhänge auf.

Best Practice Dashboard with SAP Analytics Cloud (SAC)

My colleagues and myself have talked a lot about Data Warehousing, Analytics, Reporting, Predictive and Planning in previous blogs and in several Webinars so far this year. However, we have not touched Best Practice in Dashboarding with SAP Analytics Cloud (SAC). Regardless of the solution,

Integration von Machine Learning Pipelines in die SAP Systemlandschaft

Wie kann eine Machine Learning Pipeline mit einer graphischen Benutzeroberfläche in Ihrer SAP Systemlandschaft erstellt und voll-integriert angewendet werden? In diesem Blog-Beitrag zeige ich Ihnen wie es geht. Die Screenshots wurden im Rahmen eines Workshops bei der Swiss Data Science Conference 2020 mit SAP Data

SAP Data Warehouse Cloud – Erfahrungen beim Aufbau eines Datenmodells

Sie verwenden Einkaufsdaten in Ihrem Reporting?  Profitieren Sie von unserem kostenlosen Template!Sie benötigen weitere Daten?  Profitieren Sie von unserer Erfahrung!SAP Data Warehouse Cloud ermöglicht zentrale Datenbestände leicht und intuitiv zu erweitern. Einführung in die SAP Data Warehouse Cloud (DWC) Die SAP Datawarehouse Cloud Lösung ist

Health Check Ihrer SAP EPM-Systeme?

In diesen turbulenten Zeiten kann es durchaus vorkommen, dass lang erwartete Projekte zur Ablösung alter Systeme gestoppt werden. Das ist ärgerlich, sehr schade, aber auch verständlich. Ein Health Check der bestehenden Systeme macht daher durchaus Sinn.

Die SAP Data Warehouse Cloud – ein neuer grosser (?) Wurf (Teil 2)

Administration als aller Analysis Anfang In einem neuen leeren System sind zunächst immer einige administrative Schritte notwendig, zum Glück sind es in der SAP Data Warehouse Cloud nur einige wenige, die man unbedingt erledigen muss. Natürlicherweise beginnt es mit der Userverwaltung. Das Anlegen neuer User

Die SAP Data Warehouse Cloud – ein neuer grosser (?) Wurf (Teil 1)

Was ist die SAP Data Warehouse Cloud? Wer einen Blick auf die Zukunft von SAP Produkten werfen möchte, der besitzt mit der Agenda der SAP Teched (https://events.sap.com/teched/en/home) eine ganz brauchbare Glaskugel, zumindest für die nähere Zukunft. Auf dieser Agenda zeigt sich, dass SAP mit Nachdruck

Das Internet der Dinge, Big Data und eine Fischertechnik-Fabrik – Teil 6: Hadoop vom ABAP aus ansprechen: die GLUE-Middleware von Datavard

Im vorherigen Teil wurden Daten von Steuergeräten in ein CSV-File geschrieben, dies wurde per Kafka in Hadoop importiert und via Hive-Adapter bzw. Impala-Adpater in einer HANA-Datenbank gelesen. Diese Adapter stellen eine komfortable Möglichkeit dar, um auf die Hadoop-Daten lesend zuzugreifen. Diese Adapter ermöglichen allerdings nicht

Das Internet der Dinge, Big Data und eine Fischertechnik-Fabrik – Teil 5: Visualisierung mittels CalculationView und SAP Cloud for Analytics

In den vorherigen Teilen dieses Blogs wurde gezeigt, wie die Sensordaten der Fabriksimulation schliesslich als Tabelle (genauer: als Tabellenlink) in der SAP HANA verfügbar gemacht wurde. Der nächste Schritt wäre nun beispielsweise in der HANA einen gescripteten (oder alternativ auch graphischen) CalculationView anzulegen, der die