Open SQL Part 2: SELECT Basics — Field Lists, WHERE and INTO
Write correct, efficient SELECT statements: explicit field lists instead of SELECT , WHERE conditions with ranges and patterns, ORDER BY, INTO TABLE vs INTO CORRESPONDING FIELDS, and UP TO n ROWS.
Explanation
📌 KEY POINTS
✅ Select only the columns you need — SELECT * transfers every field of wide tables.
✅ Put every possible filter into WHERE — never read rows just to throw them away in ABAP.
✅ INTO TABLE requires matching field order/types; INTO CORRESPONDING FIELDS maps by name.
💡 Use SELECT-OPTIONS directly: WHERE fldate IN s_fldate.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 1 explained Open SQL. This part covers the SELECT statement you will write every day.
━━━━━━━━━━━━━━━━━━━━
▶ 1. FIELD LIST
SELECT carrid connid fldate price currency FROM sflight INTO TABLE gt_flight …
- Less data transferred and less memory.
- On HANA (column store) fewer columns are also faster to read.
- SELECT * only if you really need (almost) all fields.
━━━━━━━━━━━━━━━━━━━━
▶ 2. WHERE CONDITIONS
- Comparison: =, <>, <, >, <=, >= (also EQ, NE, LT…).
- BETWEEN a AND b.
- IN (list) or IN range_table (SELECT-OPTIONS).
- LIKE 'LH%' — pattern (% any, _ one character).
- IS NULL / IS NOT NULL (rare for dictionary tables, relevant for outer joins).
- Combine with AND / OR; use parentheses.
Filter on key or indexed fields where possible (index topic: Performance Tuning).
━━━━━━━━━━━━━━━━━━━━
▶ 3. INTO TARGETS
- INTO TABLE itab — rows in the order of the field list must match the table line structure positionally.
- INTO CORRESPONDING FIELDS OF TABLE itab — fields matched by name; safer when structures differ (slight overhead).
- APPENDING TABLE — add to existing rows.
- Strict syntax: INTO TABLE @DATA(lt) creates a matching table.
━━━━━━━━━━━━━━━━━━━━
▶ 4. ORDER BY
- ORDER BY PRIMARY KEY or ORDER BY field1 DESCENDING.
- Sorting in the database is fine for result lists; for internal processing you may SORT in ABAP.
━━━━━━━━━━━━━━━━━━━━
▶ 5. LIMITING ROWS
UP TO n ROWS — for previews, top-N with ORDER BY, or existence checks.
━━━━━━━━━━━━━━━━━━━━
▶ 6. EMPTY RESULTS
Check sy-subrc = 4 (no rows); an empty table is valid business data — handle it (message, empty output).
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Run the code example with different selection-screen inputs.
- Compare SELECT * and a field list in ST05 (Part 8) for the same WHERE.
- Try INTO TABLE with a structure in a different field order — see why CORRESPONDING exists.
✅ CHECKPOINT: your SELECTs read exactly the rows and columns you need.
Code example
REPORT zosql_part2. TABLES sflight.SELECT-OPTIONS: s_carr FOR sflight-carrid DEFAULT 'LH', s_fldate FOR sflight-fldate. TYPES: BEGIN OF ty_flight, carrid TYPE s_carr_id, connid TYPE s_conn_id, fldate TYPE s_date, price TYPE s_price, currency TYPE s_currcode, END OF ty_flight, BEGIN OF ty_carr, carrid TYPE s_carr_id, carrname TYPE s_carrname, END OF ty_carr. DATA: gt_flight TYPE STANDARD TABLE OF ty_flight, gs_flight TYPE ty_flight, gt_other TYPE STANDARD TABLE OF sflight, gt_carr TYPE STANDARD TABLE OF ty_carr, gt_top TYPE STANDARD TABLE OF ty_flight. START-OF-SELECTION.* ===== 1. Field list + WHERE with ranges + ORDER BY ===== SELECT carrid connid fldate price currency " same order as ty_flight FROM sflight INTO TABLE gt_flight WHERE carrid IN s_carr AND fldate IN s_fldate AND seatsocc < 200 ORDER BY carrid connid fldate. IF sy-subrc <> 0. MESSAGE 'No flights for this selection' TYPE 'S' DISPLAY LIKE 'W'. RETURN. ENDIF. * ===== 2. INTO CORRESPONDING FIELDS: mapping by name ===== SELECT carrid connid fldate price currency FROM sflight INTO CORRESPONDING FIELDS OF TABLE gt_other " wide target, only 5 fields filled WHERE carrid IN s_carr. * ===== 3. Pattern search ===== SELECT carrid carrname FROM scarr INTO TABLE gt_carr WHERE carrname LIKE 'L%'. * ===== 4. Top 5 most expensive flights ===== SELECT carrid connid fldate price currency FROM sflight INTO TABLE gt_top UP TO 5 ROWS WHERE carrid IN s_carr ORDER BY price DESCENDING. LOOP AT gt_flight INTO gs_flight. WRITE: / gs_flight-carrid, gs_flight-connid, gs_flight-fldate, gs_flight-price CURRENCY gs_flight-currency, gs_flight-currency. ENDLOOP. * AVOID: SELECT * ... and then DELETE gt_flight WHERE seatsocc >= 200. -> filter in WHERE* 💡 Modern syntax: SELECT carrid, carrname FROM scarr WHERE ... INTO TABLE @DATA(lt_carr).Real project scenario
A sales report selected all fields of a 300-column document table and then deleted 95% of the rows in ABAP because only one sales organization was relevant. The report needed 20 minutes and a lot of memory.
Moving the organization and date filter into WHERE and selecting only the 12 needed columns reduced runtime to under a minute and memory to a fraction.
Common mistakes
- SELECT * on wide tables.
- Filtering in ABAP instead of WHERE.
- INTO TABLE with a different field order than the target structure.
- Leading wildcards in LIKE on large tables ('%abc').
- Not handling empty results.
Best practices
- Explicit field lists.
- All filters in WHERE; use ranges from the selection screen.
- INTO CORRESPONDING FIELDS when structures differ.
- ORDER BY when the order matters.
- UP TO n ROWS for top-N and previews.
Interview angle
Questions: "Why avoid SELECT *?", "INTO TABLE vs INTO CORRESPONDING FIELDS?", "How do you use SELECT-OPTIONS in SQL?"
Strong answer: SELECT * transfers unnecessary data and memory (especially on wide/column-store tables); INTO TABLE maps positionally, CORRESPONDING by name; SELECT-OPTIONS are used with IN in WHERE; filter everything possible in the database; handle sy-subrc 4.
Practice this lesson
Quick check
1. Which SELECT uses a selection-screen range correctly?
2. Why should explicit field lists be preferred over SELECT * on wide tables?
3. Which addition avoids duplicates in the result set of SELECT?
Interview questions
1. A monthly billing report selects every invoice and filters in ABAP. What is the fix?
Answer it in your own words first, then compare.
2. A finance extraction selects all BKPF fields for every document. How would you improve it?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- Open SQL Part 1: How ABAP Reads the Database
- Open SQL Part 10: Open SQL in Real Reports and Interfaces
- Open SQL Part 3: FOR ALL ENTRIES — Correct Use
- Open SQL Part 4: SELECT SINGLE vs UP TO 1 ROWS
- Open SQL Part 5: JOINs — When to Use and When to Avoid
- Open SQL Part 6: Aggregates, GROUP BY and HAVING
- Open SQL Part 7: PACKAGE SIZE and Large Data Processing
- Open SQL Part 8: Performance Analysis with ST05, SAT and SQL Monitor