AMDP Part 4: Parameters, Internal Tables and Client Handling
Pass data correctly between ABAP and SQLScript: allowed parameter types, internal tables as input, table variables, NULL and type differences, and safe client handling for tables and CDS views.
Explanation
📌 KEY POINTS
✅ All AMDP parameters are passed BY VALUE; elementary types and flat internal tables are allowed.
✅ Input internal tables arrive as table variables (read with :it_name); outputs are assigned (et_x = SELECT …).
✅ Client: filter tables with SESSION_CONTEXT('CLIENT'); for CDS views use the CDS SESSION CLIENT option.
⚠️ SQL NULL is not ABAP initial — use COALESCE for aggregates and outer joins.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Parts 1–3 covered the method types. This part is about the boundary between ABAP and the database.
━━━━━━━━━━━━━━━━━━━━
▶ 1. PARAMETER RULES
- Always "VALUE( … )" — no reference passing.
- Allowed: elementary types, and internal tables with flat (non-nested) line types; no references, no nested structures, no strings in structures on some releases (check the keyword docs of your release).
- Types must be compatible with database types — use DDIC-based or clearly typed fields (dates as d/dats, amounts as p/dec).
━━━━━━━━━━━━━━━━━━━━
▶ 2. INTERNAL TABLES AS INPUT
Passing a list of keys is common (e.g. customers selected in ABAP):
- In ABAP: IMPORTING VALUE(it_customers) TYPE tt_customers.
- In SQLScript it is a table variable: SELECT … FROM zsales_item AS i INNER JOIN :it_customers AS c ON c.customer = i.customer.
- Much better than building an IN list dynamically.
━━━━━━━━━━━━━━━━━━━━
▶ 3. TABLE VARIABLES INSIDE SQLSCRIPT
lt_open = SELECT …; — then use :lt_open in later statements. HANA optimizes the whole block, so steps stay set-based.
━━━━━━━━━━━━━━━━━━━━
▶ 4. NULL AND TYPE DIFFERENCES
- Outer joins and aggregates over no rows return NULL, not 0 or ''. ABAP receives initial values, but calculations inside SQLScript with NULL yield NULL.
- Use COALESCE( SUM( amount ), 0 ).
- Dates: ABAP DATS is 'YYYYMMDD' text in the database; use TO_DATE/DAYS_BETWEEN appropriately.
- Decimal precision: define result types generously and round explicitly.
━━━━━━━━━━━━━━━━━━━━
▶ 5. CLIENT HANDLING
- Tables: add mandt = SESSION_CONTEXT('CLIENT') to every client-dependent table in every statement (including joins).
- Or pass the client as a parameter (sy-mandt from ABAP) and filter on it.
- Reading CDS view entities in SQLScript: use the method option CDS SESSION CLIENT CURRENT (syntax depends on release) so client-dependent CDS views read the current client.
⚠️ WATCH OUT: forgetting one client filter in a join silently mixes data between clients.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Add IMPORTING VALUE(it_customers) to the procedure.
- Join it in SQLScript as a table variable.
- Add COALESCE for aggregated amounts.
- Check every client-dependent source has a client filter.
- Test with an empty input table and with keys that have no data.
✅ CHECKPOINT: data crosses the ABAP–HANA boundary correctly and safely.
Code example
CLASS zcl_sales_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES if_amdp_marker_hdb. TYPES: BEGIN OF ty_customer, customer TYPE c LENGTH 10, END OF ty_customer, tt_customers TYPE STANDARD TABLE OF ty_customer WITH EMPTY KEY, BEGIN OF ty_total, customer TYPE c LENGTH 10, amount TYPE p LENGTH 16 DECIMALS 2, items TYPE i, END OF ty_total, tt_totals TYPE STANDARD TABLE OF ty_total WITH EMPTY KEY. CLASS-METHODS totals_for_customers IMPORTING VALUE(it_customers) TYPE tt_customers " internal table in VALUE(iv_company_code) TYPE char4 EXPORTING VALUE(et_totals) TYPE tt_totals. " internal table outENDCLASS. CLASS zcl_sales_amdp IMPLEMENTATION. METHOD totals_for_customers BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING zsales_item. -- step 1: items of the requested customers (input table = table variable) lt_items = SELECT i.customer, i.net_amount FROM zsales_item AS i INNER JOIN :it_customers AS c ON c.customer = i.customer WHERE i.mandt = SESSION_CONTEXT( 'CLIENT' ) -- client filter AND i.company_code = :iv_company_code; -- step 2: every requested customer, even without items (NULL -> 0) et_totals = SELECT c.customer, COALESCE( SUM( t.net_amount ), 0 ) AS amount, COUNT( t.customer ) AS items FROM :it_customers AS c LEFT OUTER JOIN :lt_items AS t ON t.customer = c.customer GROUP BY c.customer; ENDMETHOD.ENDCLASS. " ===== Caller =====" DATA(customers) = VALUE zcl_sales_amdp=>tt_customers( ( customer = 'C100' ) ( customer = 'C200' ) )." zcl_sales_amdp=>totals_for_customers(" EXPORTING it_customers = customers iv_company_code = '1010'" IMPORTING et_totals = DATA(totals) ). " ===== Reading a client-dependent CDS view inside AMDP =====" METHOD m BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT" OPTIONS READ-ONLY CDS SESSION CLIENT CURRENT " (check release syntax)" USING zi_salestotals.Real project scenario
An AMDP report showed customers with no sales as missing, and in one test system some totals were doubled. Two causes: an inner join dropped customers without items, and the join to a customer text table had no client filter, so texts from two clients multiplied rows.
The fix used the input table as the driving table with a LEFT OUTER JOIN and COALESCE, and added client filters to every client-dependent source. The team added a rule to their AMDP review checklist: "count the client filters — one per client-dependent table".
Common mistakes
- Forgetting VALUE() in the signature.
- Nested or reference types in parameters.
- Building dynamic IN lists instead of passing an internal table.
- Missing client filter on joined tables.
- Ignoring NULL in aggregates and outer joins.
- Assuming ABAP date/decimal semantics in SQLScript.
Best practices
- Pass keys as internal tables and join them as table variables.
- Use table variables for readable multi-step logic.
- Filter client on every client-dependent source (or use the CDS session client option).
- Use COALESCE for aggregates and outer joins.
- Test empty inputs and keys without data.
Interview angle
Questions: "How do you pass an internal table to an AMDP?", "How is the client handled in AMDP?", "What about NULL values?"
Strong answer: parameters are passed by value; flat internal tables become table variables used with :name in joins; outputs are assigned from SELECTs; client must be filtered explicitly on each client-dependent table via SESSION_CONTEXT('CLIENT') or a parameter, and CDS views need the CDS session client option; NULLs from outer joins/aggregates need COALESCE.
Practice this lesson
Quick check
1. An AMDP sums amounts after a LEFT OUTER JOIN, and customers without items show empty totals. What fixes it?
2. Which statement about client handling in AMDP is correct?
3. Regarding parameter passing in AMDP method signatures, which rule is correct?
Interview questions
1. A report is slow because it aggregates millions of rows in ABAP. Would you move it directly to AMDP?
Answer it in your own words first, then compare.
2. How do you pass internal tables to an AMDP and handle client and NULL values correctly?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.