6.3Bloom · ANot started

CDS table function + AMDP

Reading depth

What you'll learn

When CDS can't express it, a table function over a read-only AMDP method can — but you must filter the client yourself with where mandt = :p_client.

  • Use a table function + AMDP only when CDS can't express it (recursive CTE, window functions).
  • AMDP read method: `by database function for hdb language sqlscript options read-only using ...`.
  • `options read-only` enables routing/optimization; `using` must list every referenced object.

When CDS cannot express the logic — a recursive CTE, or a window function such as `row_number()` for ranking before CDS supported it — drop one rung to a CDS table function whose body is an AMDP method. The table function declares the returned structure and parameters in DDIC-like syntax; the AMDP method supplies the SQLScript that produces those rows. The function is then consumable from Open SQL and other CDS just like a view.

The AMDP read method is implemented `by database function for hdb language sqlscript options read-only using ...`. `options read-only` tells HANA the method does not write, which lets it route and optimize the call on scale-out systems; the `using` clause must name every database object the SQLScript touches so the dependency analyzer wires activation correctly. The body returns a SELECT — here with `row_number() over ( partition by ... order by ... )` to rank rows per customer.

The non-negotiable rule is client handling: AMDP has *no implicit MANDT injection* the way Open SQL does. You must filter `where mandt = :p_client` yourself, where `p_client` is a parameter annotated `@Environment.systemField: #CLIENT` so the framework fills it with the caller's client. Forget it and the method returns cross-client data — a defect ATC's AMDP checks catch, but only when those checks are enabled in your variant.

Key points

  • Use a table function + AMDP only when CDS can't express it (recursive CTE, window functions).
  • AMDP read method: `by database function for hdb language sqlscript options read-only using ...`.
  • `options read-only` enables routing/optimization; `using` must list every referenced object.
  • No implicit client — you must filter `where mandt = :p_client` explicitly.
  • Bind the client parameter with `@Environment.systemField: #CLIENT` so the framework fills it.

Examples

CDS table function declaration

Declares the returned columns and a client parameter bound to the system field; the body lives in an AMDP method.

ABAP@EndUserText.label: 'Order Ranking'
define table function ZI_OrderRanking
  with parameters
    @Environment.systemField: #CLIENT
    p_client : abap.clnt
  returns {
    client      : abap.clnt;
    OrderId     : zorder_id;
    CustomerId  : kunnr;
    RankPerCust : abap.int4;
  }
  implemented by method zcl_order_ranking=>get;
The AMDP read method with explicit client filter

read-only, every table listed in using, and a window function — with the mandatory where mandt = :p_client because AMDP has no implicit client.

ABAPclass zcl_order_ranking definition public.
  public section.
    class-methods get for table function zi_orderranking.
endclass.

class zcl_order_ranking implementation.
  method get by database function for hdb
             language sqlscript
             options read-only
             using zorder_hdr.
    return
      select
        mandt    as client,
        order_id as "OrderId",
        kunnr    as "CustomerId",
        row_number() over ( partition by kunnr order by total desc )
                 as "RankPerCust"
      from zorder_hdr
      where mandt = :p_client;
  endmethod.
endclass.

Source notes: clean-core-curriculum §6.3

Ask Claude

Build a prompt from this lesson + your question and open a fresh Claude chat with it pre-filled — handy for adapting a before/after pattern to your own object.