Write an AMDP that respects MANDT
What you'll learn
AMDP has no implicit client, so carry the client column in the returns list, take it as a @Environment.systemField #CLIENT parameter, filter where mandt = :p_client, and let ATC's AMDP check confirm it.
- 1. Include the client column in both the returns list and the source SELECT.
- 2. Declare a parameter with @Environment.systemField: #CLIENT typed abap.clnt.
- 3. Filter explicitly in SQLScript: where mandt = :p_client.
Open SQL injects the client automatically, but AMDP does not: SQLScript runs on the database and sees the raw tables, so a careless table function returns rows from every client. A cross-client leak is a real defect, not a style nit, and the fix is to handle MANDT explicitly at three points that must agree.
First, the client column must appear both in the table function's returns list and in the underlying source SELECT, so the client travels with each row. Second, you declare a parameter annotated @Environment.systemField: #CLIENT typed abap.clnt; the framework binds the caller's client into that parameter at runtime. Third, the SQLScript body filters on it explicitly with a predicate such as where mandt = :p_client.
Because nothing in the language forces this, you confirm it with tooling: ATC's AMDP client-handling check flags a table function or procedure that reads a client-dependent table without filtering the client. Enable that check in your variant so the safety net catches the omission that the compiler will not.
Key points
- 1. Include the client column in both the returns list and the source SELECT.
- 2. Declare a parameter with @Environment.systemField: #CLIENT typed abap.clnt.
- 3. Filter explicitly in SQLScript: where mandt = :p_client.
- 4. Confirm with ATC's AMDP client-handling check, enabled in your variant.
Examples
The SQLScript reads the raw table with no client predicate, so it returns rows from every client — a defect Open SQL would have prevented.
ABAPmethod get by database function for hdb
language sqlscript
options read-only
using zorder_hdr.
return
select order_id as "OrderId", kunnr as "CustomerId", total
from zorder_hdr;
endmethod.The client is a #CLIENT parameter, carried in the returns list, and filtered explicitly with where mandt = :p_client.
ABAPdefine table function zi_orderranking
with parameters
@Environment.systemField: #CLIENT
p_client : abap.clnt
returns {
client : abap.clnt;
orderid : zorder_id;
customerid : kunnr;
}
implemented by method zcl_order_ranking=>get;
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"
from zorder_hdr
where mandt = :p_client;
endmethod.Source notes: clean-core-curriculum §12.8
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.