2.2Bloom · AnNot started

Common HANA pitfalls

Reading depth

What you'll learn

The classic traps: ORDER BY is no longer free, partial-key SELECT SINGLE is arbitrary, and an empty FOR ALL ENTRIES driver returns every row — so guard it.

  • ORDER BY is not free — request it explicitly when you depend on order.
  • SELECT SINGLE on a partial key returns an arbitrary row; supply the full key.
  • FOR ALL ENTRIES de-duplicates the driver AND returns ALL rows on an empty driver — guard it.

The classics all stem from the §2.1 shifts. ORDER BY is no longer free — if you assumed sorted output you now read 'random' rows; and SELECT SINGLE without a fully-qualified key returns an arbitrary matching row, which on HANA is often a different one than before. The fix for both is to be explicit: request the order you depend on, and never SELECT SINGLE on a partial key when you mean 'a specific row.'

FOR ALL ENTRIES carries two pitfalls that are more damaging under HANA because result-set sizes differ: it silently de-duplicates the driver table, and — critically — an empty driver table returns ALL rows of the target, not none. Always guard with IF lines( itab ) > 0 before the FAE, or you will table-scan production.

The remaining classics are quieter: implicit type conversion in a WHERE clause (comparing a CHAR18 MATNR to a short literal forces padding and can drop the index), COUNT(*) on a wide column-store table is a column scan rather than a free metadata read, and LIKE behaviour depends on HANA collation so CDS pattern filters should use the escape mechanism.

Key points

  • ORDER BY is not free — request it explicitly when you depend on order.
  • SELECT SINGLE on a partial key returns an arbitrary row; supply the full key.
  • FOR ALL ENTRIES de-duplicates the driver AND returns ALL rows on an empty driver — guard it.
  • Implicit type conversion in WHERE can cost the index; match the field's type.
  • COUNT(*) with a filter on a non-key column is a column scan, not a free count.

Examples

BeforeUnguarded FOR ALL ENTRIES

If lt_keys is empty, this returns every row of mara — a full table scan nobody intended.

ABAPselect matnr, mtart from mara
  for all entries in @lt_keys
  where matnr = @lt_keys-matnr
  into table @data(lt_mara).
AfterGuarded FOR ALL ENTRIES

The empty-driver guard turns the dangerous all-rows case into a deliberate no-op.

ABAPif lt_keys is not initial.
  select matnr, mtart from mara
    for all entries in @lt_keys
    where matnr = @lt_keys-matnr
    into table @data(lt_mara).
endif.
BeforeRelying on implicit order

On HANA the 'first' row here is undefined — the read is not ordered.

ABAPselect matnr, ersda from mara
  into table @data(lt_mara)
  up to 10 rows.
AfterRequesting the order you depend on

An explicit ORDER BY makes the 'first 10' deterministic.

ABAPselect matnr, ersda from mara
  order by ersda descending
  into table @data(lt_mara)
  up to 10 rows.

Pitfalls

  • Forgetting the IF lines( itab ) > 0 guard before FOR ALL ENTRIES — the empty-driver case silently returns all rows.
  • Trusting SELECT ... UP TO n ROWS without ORDER BY to be deterministic.

Source notes: clean-core-curriculum §2.2

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.