Eingebettete (oder anonyme) Funktionen in SQLScript

Eingebettete (oder anonyme) Funktionen in SQLScript

Veröffentlicht am 8. November 2019 von

Jörg Brandeis

| News | SQLScript |

Mit SAP HANA 2.0 SPS04 ist mit den eingebetteten Funktionen ein weiteres Feature zur Sprache SQLScript hinzugekommen. Diese ermöglichen die Verwendung von imperativem SQLScript Code innerhalb einer SELECT Abfrage. Diese Funktionen werden nur für exakt diese eine Abfrage erstellt und nur dort ausgeführt. Da diese Funktionen keinen Namen bekommen, werden sie auch als Anonyme Funktionen bezeichnet.

head 1597555 640

Im folgenden Beispiel wird die Abfrage mit einer eingebetteten Funktion innerhalb einer Prozedur aufgerufen.

  • Die eingebettete Funktion beginnt mit Zeile 11 und endet in Zeile 37. Sie enthält imperatives Coding, womit die ganze Prozedur imperativ ist.
  • Der Parameter IV_MAX der Prozedur wird in Zeile 11 an den Parameter IV_A der Funktion weitergegeben. Dieser wird dann in Zeile 24 als Obergrenze für die FOR-Schleife verwendet wird. Ein direkter Zugriff auf IV_MAX innerhalb der Funktion ist nicht möglich.
  • Die WHERE-Bedingung in Zeile 38 verdeutlicht nochmals, dass es sich um eine Abfrage handelt
  • Mit der CALL Anweisung in Zeile 41 können Sie die Prozedur testen.
CREATE PROCEDURE test_anonymous_function
  (IN iv_max INT,
   OUT ot_result TABLE(number INTEGER, 
                       letter VARCHAR ) )
AS BEGIN
 ot_result = 
   SELECT number,
          letter
          
   FROM 
        SQL FUNCTION (IN iv_a INT => :iv_max)
        RETURNS TABLE (number INT, 
                       letter VARCHAR(1))
        BEGIN
          DECLARE lv_cnt INT;
          DECLARE lv_chars VARCHAR(30)   
                           DEFAULT 'ABCDEFGHIJKLMNOP';
          
          lt_result = SELECT 0   AS number,
                             ' ' AS letter 
                      FROM dummy 
                      WHERE dummy <> 'X';       
          
          FOR lv_cnt IN 1..:iv_a DO
          
            lt_result = SELECT * FROM :lt_result 
                          UNION
                        SELECT lv_cnt AS number,
                               SUBSTRING(:lv_chars, 
                                         :lv_cnt, 
                                         1) AS letter
                          FROM dummy;
                          
          END FOR;
          
          RETURN SELECT * FROM :lt_result;
        END
   WHERE MOD(number, 2) = 0 ; 
END;

CALL test_anonymous_function(13, ?);

Von der Verwendung von eingebetteten Funktionen rate ich grundsätzlich ab, da bereits einfache Funktionen die Lesbarkeit des Codes erheblich verschlechtern. Dies konnten Sie auch deutlich an dem gezeigten Beispiel sehen.

Als Alternative bietet sich die Anlage einer separaten UDF-Funktion an oder die Zerlegung der Abfrage in zwei Schritte:

  • Erzeugung einer Tabellenvariablen mit dem imperativen Code
  • Abfrage auf diese Tabellenvariable

Durch diese Zerlegung lässt sich der Code besser lesen. Und es ist im Debugger möglich, die Zwischenergebnisse zu betrachten. Manchmal sind diese Alternativen aber aus technischen Gründen nicht möglich. Dann erlauben uns die eingebetteten Funktionen die Nutzung von imperativem Code direkt in einer Abfrage.

SAP Dokumentation zu eingebetteten Funktionen