Declarative, projected, joined
What you'll learn
Replace a SELECT SINGLE in a loop with FOR ALL ENTRIES, and ideally a single INNER JOIN or CDS view — one set-based read instead of N round trips.
- Anti-pattern: SELECT SINGLE inside LOOP AT — one round trip per row.
- Better: FOR ALL ENTRIES — one statement, but you merge and de-dup yourself.
- Best: a single INNER JOIN, or a CDS view consumed by one SELECT.
The single most common performance fix in custom ABAP is collapsing per-row database access into one set-based read. The anti-pattern is a `SELECT SINGLE` inside a `LOOP AT`: for every order you fire a separate query for the customer name, so a thousand orders cost a thousand round trips. The optimizer never sees the whole problem, and the application server spends its time waiting on the network.
The first improvement is FOR ALL ENTRIES: collect the keys, issue one statement, and merge the result back in ABAP. This cuts a thousand round trips to one, but you still de-duplicate the driver, must guard the empty-driver case, and do the join logic yourself in ABAP. It is better, not best — a useful middle step when the join cannot yet be expressed declaratively.
The winning form is a single INNER JOIN — or, better still, a CDS view consumed by one SELECT. You name exactly the columns you need, the join happens on HANA where the data lives, and the optimizer can choose the plan. The same three columns that took a thousand queries now take one projected, joined statement. Internalize the progression — per-row SELECT SINGLE → FOR ALL ENTRIES → a single join or CDS — because you will apply it again and again.
Key points
- Anti-pattern: SELECT SINGLE inside LOOP AT — one round trip per row.
- Better: FOR ALL ENTRIES — one statement, but you merge and de-dup yourself.
- Best: a single INNER JOIN, or a CDS view consumed by one SELECT.
- Name the columns and let the join run on HANA where the data lives.
- The progression per-row → FAE → join/CDS recurs constantly in custom code.
Examples
One query per order to fetch the customer name — N round trips, no set-based optimization.
ABAPloop at lt_orders assigning field-symbol(<o>).
select single name1 from kna1
into @<o>-customer_name
where kunnr = @<o>-customer_id.
endloop.One statement instead of N, but you still de-duplicate the driver, guard the empty case, and stitch the result back by hand.
ABAPselect kunnr, name1
from kna1
for all entries in @lt_orders
where kunnr = @lt_orders-customer_id
into table @data(lt_kna1).
" ... then loop and merge name1 into lt_ordersNamed columns, the join executed on HANA, the optimizer free to choose the plan; one statement does it all (a CDS view would be cleaner still).
ABAPselect o~order_id, o~customer_id,
k~name1 as customer_name, o~total
from zorder_hdr as o
inner join kna1 as k on k~kunnr = o~customer_id
where o~status = 'OPEN'
into table @data(lt_result).Source notes: clean-core-curriculum §7.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.