AMDP (ABAP Managed Database Procedures) permet l’implémentation de procédures SQLScript directement dans les classes ABAP. Le code est exécuté sur la base de données SAP HANA et offre des performances optimales pour les opérations gourmandes en données.
Prérequis
- SAP HANA comme base de données
- ABAP 7.40 SP05 ou supérieur
- La classe doit implémenter l’interface
IF_AMDP_MARKER_HDB
Structure de base
CLASS zcl_amdp_example DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES: if_amdp_marker_hdb.
TYPES: BEGIN OF ty_result, field1 TYPE string, field2 TYPE i, END OF ty_result, ty_results TYPE STANDARD TABLE OF ty_result WITH EMPTY KEY.
CLASS-METHODS: get_data IMPORTING VALUE(iv_param) TYPE string EXPORTING VALUE(et_result) TYPE ty_results.ENDCLASS.
CLASS zcl_amdp_example IMPLEMENTATION. METHOD get_data BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING ztable.
et_result = SELECT field1, field2 FROM ztable WHERE field1 = :iv_param; ENDMETHOD.ENDCLASS.Exemples
1. Procédure AMDP simple
CLASS zcl_customer_amdp DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES: if_amdp_marker_hdb.
TYPES: BEGIN OF ty_customer, kunnr TYPE kunnr, name1 TYPE name1_gp, ort01 TYPE ort01_gp, land1 TYPE land1_gp, END OF ty_customer, ty_customers TYPE STANDARD TABLE OF ty_customer WITH EMPTY KEY.
CLASS-METHODS: get_customers_by_country IMPORTING VALUE(iv_country) TYPE land1_gp EXPORTING VALUE(et_customers) TYPE ty_customers.ENDCLASS.
CLASS zcl_customer_amdp IMPLEMENTATION. METHOD get_customers_by_country BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING kna1.
et_customers = SELECT kunnr, name1, ort01, land1 FROM kna1 WHERE land1 = :iv_country; ENDMETHOD.ENDCLASS.
" AppelDATA: lt_customers TYPE zcl_customer_amdp=>ty_customers.
zcl_customer_amdp=>get_customers_by_country( EXPORTING iv_country = 'DE" IMPORTING et_customers = lt_customers).
LOOP AT lt_customers INTO DATA(ls_cust). WRITE: / ls_cust-kunnr, ls_cust-name1, ls_cust-ort01.ENDLOOP.2. AMDP avec plusieurs tables
CLASS zcl_order_amdp DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES: if_amdp_marker_hdb.
TYPES: BEGIN OF ty_order_detail, vbeln TYPE vbeln_va, posnr TYPE posnr_va, matnr TYPE matnr, kwmeng TYPE kwmeng, netwr TYPE netwr, kunnr TYPE kunnr, name1 TYPE name1_gp, END OF ty_order_detail, ty_order_details TYPE STANDARD TABLE OF ty_order_detail WITH EMPTY KEY.
CLASS-METHODS: get_order_details IMPORTING VALUE(iv_vbeln) TYPE vbeln_va EXPORTING VALUE(et_details) TYPE ty_order_details.ENDCLASS.
CLASS zcl_order_amdp IMPLEMENTATION. METHOD get_order_details BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING vbak vbap kna1.
et_details = SELECT p.vbeln, p.posnr, p.matnr, p.kwmeng, p.netwr, h.kunnr, c.name1 FROM vbap AS p INNER JOIN vbak AS h ON p.vbeln = h.vbeln INNER JOIN kna1 AS c ON h.kunnr = c.kunnr WHERE p.vbeln = :iv_vbeln; ENDMETHOD.ENDCLASS.3. AMDP avec variables et logique
CLASS zcl_sales_amdp DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES: if_amdp_marker_hdb.
TYPES: BEGIN OF ty_sales_summary, kunnr TYPE kunnr, name1 TYPE name1_gp, order_count TYPE i, total_value TYPE netwr, END OF ty_sales_summary, ty_sales_summaries TYPE STANDARD TABLE OF ty_sales_summary WITH EMPTY KEY.
CLASS-METHODS: get_sales_summary IMPORTING VALUE(iv_year) TYPE gjahr EXPORTING VALUE(et_summary) TYPE ty_sales_summaries.ENDCLASS.
CLASS zcl_sales_amdp IMPLEMENTATION. METHOD get_sales_summary BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING vbak kna1.
-- Variable locale pour la plage de dates DECLARE lv_from_date DATE; DECLARE lv_to_date DATE;
lv_from_date = CONCAT(:iv_year, '0101'); lv_to_date = CONCAT(:iv_year, '1231');
-- Requête agrégée et_summary = SELECT k.kunnr, k.name1, COUNT(*) AS order_count, SUM(v.netwr) AS total_value FROM vbak AS v INNER JOIN kna1 AS k ON v.kunnr = k.kunnr WHERE v.erdat BETWEEN :lv_from_date AND :lv_to_date GROUP BY k.kunnr, k.name1 ORDER BY total_value DESC; ENDMETHOD.ENDCLASS.4. AMDP avec logique IF/CASE
METHOD calculate_discount BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING zcustomers.
et_result = SELECT kunnr, name1, total_sales, CASE WHEN total_sales >= 100000 THEN 15 WHEN total_sales >= 50000 THEN 10 WHEN total_sales >= 10000 THEN 5 ELSE 0 END AS discount_percent FROM zcustomers;ENDMETHOD.5. AMDP avec boucles
METHOD process_data BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING ztable.
DECLARE lv_counter INTEGER; DECLARE lv_max INTEGER;
-- Charger les données lt_data = SELECT * FROM ztable;
-- Initialiser le compteur lv_counter = 1; SELECT COUNT(*) INTO lv_max FROM :lt_data;
-- Boucle WHILE lv_counter <= lv_max DO -- Traitement lv_counter = lv_counter + 1; END WHILE;
et_result = SELECT * FROM :lt_data;ENDMETHOD.6. AMDP avec tables temporaires
METHOD complex_calculation BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING vbak vbap.
-- Première table temporaire lt_headers = SELECT vbeln, kunnr, erdat, netwr FROM vbak WHERE erdat >= ADD_DAYS(CURRENT_DATE, -365);
-- Deuxième table temporaire basée sur la première lt_items = SELECT p.* FROM vbap AS p INNER JOIN :lt_headers AS h ON p.vbeln = h.vbeln;
-- Agrégation lt_summary = SELECT h.kunnr, COUNT(DISTINCT h.vbeln) AS order_count, SUM(i.netwr) AS item_total FROM :lt_headers AS h INNER JOIN :lt_items AS i ON h.vbeln = i.vbeln GROUP BY h.kunnr;
-- Résultat et_result = SELECT * FROM :lt_summary;ENDMETHOD.7. Fonction de table CDS
" Définition de vue CDS@EndUserText.label: 'Sales by Customer (Table Function)"define table function ZTF_SALES_BY_CUSTOMER with parameters @Environment.systemField: #SYSTEM_DATE p_date : abap.dats returns { key kunnr : abap.char(10); name1 : abap.char(35); total : abap.dec(15,2); } implemented by method zcl_tf_sales=>get_sales;
" Implémentation ABAPCLASS zcl_tf_sales DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES: if_amdp_marker_hdb.
CLASS-METHODS: get_sales FOR TABLE FUNCTION ztf_sales_by_customer.ENDCLASS.
CLASS zcl_tf_sales IMPLEMENTATION. METHOD get_sales BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING vbak kna1.
RETURN SELECT k.kunnr, k.name1, SUM(v.netwr) AS total FROM vbak AS v INNER JOIN kna1 AS k ON v.kunnr = k.kunnr WHERE v.erdat <= :p_date GROUP BY k.kunnr, k.name1; ENDMETHOD.ENDCLASS.
" Utilisation en ABAPSELECT * FROM ztf_sales_by_customer( p_date = @sy-datum ) INTO TABLE @DATA(lt_sales).8. AMDP avec gestion des erreurs
METHOD process_with_error BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING ztable.
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN -- Gestion des erreurs et_errors = SELECT ::SQL_ERROR_CODE AS error_code, ::SQL_ERROR_MESSAGE AS error_message FROM DUMMY; END;
-- Traitement normal et_result = SELECT * FROM ztable;ENDMETHOD.9. AMDP avec USING d’un autre AMDP
CLASS zcl_amdp_chain DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES: if_amdp_marker_hdb.
CLASS-METHODS: helper_method IMPORTING VALUE(iv_input) TYPE string EXPORTING VALUE(et_result) TYPE ty_results.
CLASS-METHODS: main_method EXPORTING VALUE(et_final) TYPE ty_finals.ENDCLASS.
CLASS zcl_amdp_chain IMPLEMENTATION. METHOD helper_method BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING ztable.
et_result = SELECT * FROM ztable WHERE field = :iv_input; ENDMETHOD.
METHOD main_method BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING zcl_amdp_chain=>helper_method.
-- Appeler un autre AMDP CALL "ZCL_AMDP_CHAIN=>HELPER_METHOD"( iv_input => 'VALUE', et_result => lt_temp );
et_final = SELECT * FROM :lt_temp; ENDMETHOD.ENDCLASS.10. Performance : AMDP vs. Open SQL
" === Open SQL (Standard) ===" Les données sont transférées du serveur DB au serveur AppSELECT * FROM vbak INTO TABLE @DATA(lt_orders).
LOOP AT lt_orders INTO DATA(ls_order). " Traitement sur le serveur App IF ls_order-netwr > 10000. " ... ENDIF.ENDLOOP.
" === AMDP (optimisé) ===" Traitement directement sur la base de donnéeszcl_order_amdp=>get_high_value_orders( EXPORTING iv_min_value = 10000 IMPORTING et_orders = lt_high_value_orders)." Seules les données pertinentes sont transférées11. AMDP avec fonctions de fenêtrage
METHOD get_ranked_sales BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING vbak.
et_result = SELECT kunnr, vbeln, netwr, ROW_NUMBER() OVER ( PARTITION BY kunnr ORDER BY netwr DESC ) AS rank_per_customer, SUM(netwr) OVER ( PARTITION BY kunnr ) AS total_per_customer FROM vbak;ENDMETHOD.12. Exemple pratique : Résolution de hiérarchie
METHOD resolve_hierarchy BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING zorg_units.
-- Résolution de hiérarchie récursive avec HANA et_hierarchy = SELECT node_id, parent_id, name, HIERARCHY_LEVEL AS level FROM HIERARCHY ( SOURCE ( SELECT * FROM zorg_units ) START WHERE parent_id IS NULL NO ORPHANS );ENDMETHOD.Bases de SQLScript
-- VariablesDECLARE lv_var INTEGER;DECLARE lv_text NVARCHAR(100);
-- Affectationlv_var = 42;lv_text = 'Hello';
-- Variable de tablelt_data = SELECT * FROM table;
-- Condition IFIF :lv_var > 10 THEN -- ...ELSEIF :lv_var > 5 THEN -- ...ELSE -- ...END IF;
-- Boucle WHILEWHILE :lv_counter < 100 DO lv_counter = lv_counter + 1;END WHILE;
-- Boucle FORFOR i IN 1..10 DO -- ...END FOR;
-- CurseurFOR row AS cursor_name DO -- row.fieldEND FOR;Remarques importantes / Bonnes pratiques
- AMDP uniquement pour SAP HANA – non portable vers d’autres bases de données.
- READ-ONLY pour les opérations de lecture (par défaut, recommandé).
- USING déclare tous les objets de base de données et AMDP utilisés.
- Utilisez Table Functions pour une utilisation dans les vues CDS.
- Grandes quantités de données à traiter sur la DB plutôt que de les transférer.
- IF_AMDP_MARKER_HDB doit être implémenté.
- Testez dans HANA Studio ou SQL Console.
- Débogage possible via le débogueur HANA (à partir de 7.50).
- Évitez trop de boucles – pensez en termes d’ensembles.
- Combinez avec Vues CDS pour un modèle de données optimal.