Die SAP HANA Datenbank bietet viele nützliche und coole Funktionen, die über openSQL/ABAP SQL hinaus gehen. Um auf diese Features zuzugreifen und die ganze Power der HANA Datenbank nutzen zu können, gibt es ABAP Managed Database Procedures – AMDP. Damit kann man, ähnlich wie mit EXEC SQL bzw. ADBC (ABAP Database Connectivity), native Datenbank Statements absetzen. In diesem Blogbeitrag beschäftigen wir uns mit den nötigen Anlage- und Implementierungsschritten.
AMDP Klasse und Methode anlegen
AMDP werden als spezielle Methode in einer ABAP Klasse implementiert – die Definition erfolgt wie bei jeder anderen Klasse:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CLASS /cadaxo/cl_ui38_dmo_order_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_amdp_marker_hdb. TYPES: ty_orders TYPE STANDARD TABLE OF /CADAXO/UI38D_Demo_Orders WITH DEFAULT KEY. METHODS search_orders IMPORTING VALUE(i_search_term) TYPE string EXPORTING VALUE(e_orders) TYPE ty_orders. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. |
Durch das Interface IF_AMDP_MARKER_HDB wird die Klasse besonders, was man im Implementierungs-Teil sehen kann:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
CLASS /cadaxo/cl_ui38_dmo_order_amdp IMPLEMENTATION. METHOD search_orders BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING /cadaxo/ui38d_demo_orders. e_orders = select OrderId, CustomerId, ProductId, OrderDate, Quantity, Unit, TotalPrice, Currency, Description, Name, from "/CADAXO/UI38D_DEMO_ORDERS"; ENDMETHOD. ENDCLASS. |
Die Methodenimplementierung hat einige zusätzliche Statements – Details dazu gibt es auf https://help.sap.com/doc/abapdocu_750_index_htm/7.50/de-de/abapmethod_by_db_proc.htm
BY DATABASE PROCEDURE | „Ich bin eine AMDP.“ |
FOR HDB | Derzeit nur „HDB“ – Kommen auch andere Datenbanken?!?! |
LANGUAGE SQLSCRIPT | Wir nehmen SQLSCRIPT. |
OPTIONS READ-ONLY | Wir lesen nur, geändert wird nicht! |
USING /cadaxo/ui38d_demo_orders | Wir wollen die Bestellungen aus /cadaxo/ui38d_demo_orders. |
AMDP Method aufrufen
Aufgerufen wir die AMDP Methode wie jede andere auch:
1 2 |
new /cadaxo/cl_ui38_dmo_order_amdp( )->search_orders( EXPORTING i_search_term = 'Hat Nägel' IMPORTING e_orders = data(orders) ). |
Fuzzy Search
Ok, der SELECT ist nicht gerade spektakulär – das geht auch mit ABAP SQL. Aber eine fehlertolerante Fuzzy Search?!?
Wir wollen Bestellungen zu Kundennamen finden, auch wenn wir den nicht so ganz genau kennen. Dabei hilft uns CONTAINS und FUZZY – https://help.sap.com/docs/SAP_HANA_PLATFORM/691cb949c1034198800afde3e5be6570/9a4da8f6f23b4ebf95c98f1104a56db4.html?&locale=en-US
Wir erweitern den SELECT um eine WHERE Klausel und suchen wie folgt nach dem Namen:
1 2 3 4 5 6 7 8 9 10 11 12 |
e_orders = select OrderId, CustomerId, ProductId, OrderDate, Quantity, Unit, TotalPrice, Currency, Description, Name from "/CADAXO/UI38D_DEMO_ORDERS" where contains( Name, :i_search_term, fuzzy( 0.5 ) ); |
Die FUZZY Funktion liefert alle Namen zurück, deren Vergleich mit dem I_Search_Term mindestens einen Score von 0.5 ergibt. Das klingt erstmal einfach, kann aber ziemlich knifflig werden, vor allem, wenn man die Treffermenge, Genauigkeit und Relevanz für Benutzer optimieren möchte. Der passende Schwellenwert ist dann oft nur empirisch ermittelbar.
SCORE
Um den errechneten Wert der Übereinstimmung anzuzeigen und danach zu sortieren, gibt es die Funktion SCORE. Mit FUZZY( 0.0) werden alle Namen mit einem ermittelten Score größer 0 ausgegeben.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
e_orders = select OrderId, CustomerId, ProductId, OrderDate, Quantity, Unit, TotalPrice, Currency, Description, Name, score( ) as Score from "/CADAXO/UI38D_DEMO_ORDERS" where contains( Name, :i_search_term, fuzzy( 0.0 ) ); |
Eine Suche nach „Hat Nägel“ ergibt dann z.B. folgende Trefferliste:
Komplettes Coding
Das ganze Coding sieht folgendermaßen aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
CLASS /cadaxo/cl_ui38_dmo_order_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. INTERFACES if_amdp_marker_hdb. TYPES: ty_score TYPE p LENGTH 3 DECIMALS 2. TYPES: BEGIN OF ty_order. INCLUDE TYPE /CADAXO/UI38D_Demo_Orders. TYPES: Score TYPE ty_score, END OF ty_order. TYPES: ty_orders TYPE STANDARD TABLE OF ty_order WITH DEFAULT KEY. METHODS search_orders IMPORTING VALUE(i_search_term) TYPE string EXPORTING VALUE(e_orders) TYPE ty_orders. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS /cadaxo/cl_ui38_dmo_order_amdp IMPLEMENTATION. METHOD search_orders BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING /cadaxo/ui38d_demo_orders. e_orders = select OrderId, CustomerId, ProductId, OrderDate, Quantity, Unit, TotalPrice, Currency, Description, Name, score( ) as Score from "/CADAXO/UI38D_DEMO_ORDERS" where contains( Name, :i_search_term, fuzzy( 0.0 ) ); ENDMETHOD. METHOD if_oo_adt_classrun~main. new /cadaxo/cl_ui38_dmo_order_amdp( )->search_orders( EXPORTING i_search_term = 'Hat Nägel' IMPORTING e_orders = data(orders) ). out->write( name = 'Bestellungen zur Suche:' && '`Hat Nägel`' data = orders ). ENDMETHOD. ENDCLASS. |