You look up a vendor with READ TABLE ... BINARY SEARCH in a standard table you believed was sorted, and a row that is clearly there comes back as "not found". No dump, no syntax error; only the result is wrong. After reading this you will be able to check the three sort conditions a binary search expects, use sy-subrc and sy-tabix correctly on a miss, and decide when to switch to a sorted secondary key.
The example is a standard table lt_vendors whose rows use a fictional structure ty_vendor (vendor lifnr, name name). Five rows were inserted in the order V-0040, V-0010, V-0050, V-0020, V-0030, and we look for V-0020. The vendor values and the program are invented, and the code was not run on a real system. The behaviour comes from READ TABLE, free_key and READ TABLE itab in the ABAP Keyword Documentation (7.58 and 7.50 editions).
A binary search trusts the sort and discards half
Without BINARY SEARCH, a standard table is searched linearly from the first row. That may be slow, but a row that is there is always found. With BINARY SEARCH, the table is searched binarily: compare with a middle row, keep the front half if the key is smaller and the back half if it is larger. For tables from roughly 100 rows this can cut the runtime considerably. In return, the table must be sorted in ascending order by the search key's columns; if it is not, the correct row is usually not found.
Tracing the fictional example with a textbook halving: V-0020 is smaller than V-0050 in row 3, so only rows 1 and 2 remain; it is smaller than V-0040 in row 1 too, so nothing is left to check. V-0020 is in row 4, in the discarded half. The documentation does not say which rows the kernel actually probes, so this path is only an illustration. What the documentation guarantees is that the result cannot be trusted when the sort is wrong. Sort first with SORT lt_vendors BY lifnr. and V-0020 moves to row 2; the read finds it with sy-subrc 0 and sy-tabix 2, the row number found.
The important part is that nothing at runtime stops this mistake for a standard table. The exception ITAB_ILLEGAL_BINARY_SEARCH in the documented list is for sorted tables whose search key is not an initial part of the table key. The list has no exception for an unsorted standard table, so the wrong result passes quietly into the next piece of logic.
Wrong even with a SORT
Before trusting a SORT in the code, check three things. First, the sort priority must match the order of the columns in the search key exactly. Sorting with SORT ... BY werks matnr and searching with WITH KEY matnr = ... werks = ... breaks the condition. Second, the sort must be ascending; a table sorted DESCENDING does not qualify. The binary search assumes the default sort by size, which for strings means comparing the binary representation, so a table sorted AS TEXT by the locale's text rules can give unexpected results. Third, the order must still hold at the READ. A row appended with APPEND after the sort is not in its sort position.
The rules also depend on the table category. For a sorted table, BINARY SEARCH may be written only when the search key is an initial part of the primary key or includes it, and then it has no special effect, because the read already searches binarily in key order. For a hashed table, BINARY SEARCH is not allowed.
sy-subrc and sy-tabix on a miss
When the sort is right, the return values carry useful information. Searching V-0020 in the sorted fictional table V-0010 to V-0050 gives sy-subrc 0 and sy-tabix 2. If several rows share the key, the one with the lowest row number is read. Searching a missing value such as V-0025 gives sy-subrc 4, and sy-tabix is 3, the position where INSERT ... INDEX would keep the order. Searching V-0060, larger than the last row, reaches the end: sy-subrc is 8 and sy-tabix is the number of rows plus one, 6. On a miss without a binary search, sy-tabix is undefined.
This is the trap in the common "insert in sort position if missing" pattern. Checking only IF sy-subrc = 4. misses values that belong after the end (8). INSERT ... INDEX with the row count plus one appends the row as the last one, so checking IF sy-subrc <> 0. and inserting at sy-tabix handles both cases.
Read the markers on the screen above as a review checklist. Marker 1 is a read with BINARY SEARCH and no sort, which can miss an existing row. Marker 2 is the sort by the search key's column, ascending. Marker 3 is a check for 4 only, which misses inserting after the end. Marker 4 is the alternative: a sorted secondary key that searches binarily without SORT.
Alternatives and release differences
The documentation recommends sorted tables or sorted secondary keys instead of BINARY SEARCH. Give a standard table a sorted secondary key such as WITH UNIQUE SORTED KEY by_lifnr COMPONENTS lifnr and read with WITH KEY by_lifnr COMPONENTS lifnr = ...: the secondary index is searched binarily on its own, no SORT is needed, and the order is kept with the key as rows are inserted. sy-tabix then refers to the secondary index, so when that value feeds a later index operation, the same key must be specified. If a suitable secondary key exists and is not used, the syntax check warns.
The rules in this note read the same in the 7.50 and 7.58 editions: the ascending and sort-priority requirement, the limits for sorted and hashed tables, the caution about AS TEXT, reading the first row when several match, sy-subrc 4 and 8, and sy-tabix as the insert position. The 7.58 edition adds a hint naming CL_ABAP_ITAB_UTILITIES=>READ_BINARY_SEARCH_CHECK as a way to check whether the required sort exists; the same section of the 7.50 edition does not have it. Check that the class exists in the documentation for your own release before relying on it.
What to check in your code
For each BINARY SEARCH in an existing program, check three things. Is there a SORT right before it by the same columns, in the same order, ascending? Does nothing, such as an APPEND or another sort, come between that SORT and the READ? Is a miss tested with sy-subrc <> 0? In new code, it is safer to hand the sort to the table declaration with a sorted secondary key or a sorted table.
If you remember only one thing, make it this: BINARY SEARCH is a promise that the table is sorted by the search key right now, and nothing checks that promise for you.
Add your perspective.
Share a question, another approach, or something you have tried.
Checking sign-in…
Loading comments…