ABAP & SAP Data & tekst
Data & tekst

ABAP SQL & CDS-views

Data lezen en schrijven met ABAP SQL (Open SQL): SELECT in alle varianten, joins, aggregaties, FOR ALL ENTRIES, moderne expressies in SQL, en CDS-views als moderne datamodellen.

Op deze pagina

01SELECT: data lezen

ABAP SQL (voorheen Open SQL) is SAP's database-onafhankelijke SQL-dialect, direct in de taal ingebouwd. De moderne schrijfwijze gebruikt komma's tussen velden en een @ voor ABAP-variabelen ("host variables").

" Meerdere rijen in een interne tabel
SELECT matnr, mtart, matkl
  FROM mara
  WHERE mtart = @lv_mtart
    AND matnr IN @s_matnr
  INTO TABLE @DATA(lt_mara)
  UP TO 100 ROWS.

" Eén rij
SELECT SINGLE matnr, mtart
  FROM mara
  WHERE matnr = @lv_matnr
  INTO @DATA(ls_mara).

IF sy-subrc <> 0.
  " niets gevonden — ALTIJD checken
ENDIF.

Aggregatie & groepering

SELECT matkl, COUNT( * ) AS aantal, SUM( ntgew ) AS gewicht
  FROM mara
  GROUP BY matkl
  HAVING COUNT( * ) > 10
  ORDER BY aantal DESCENDING
  INTO TABLE @DATA(lt_stats).

Beschikbaar: COUNT, SUM, AVG, MIN, MAX, en SELECT DISTINCT voor unieke rijen.

02Joins, FOR ALL ENTRIES & subqueries

Tabellen combineren — en het beruchte alternatief wanneer één van de "tabellen" een interne tabel is.

Joins

SELECT k~vbeln, k~erdat, p~posnr, p~matnr, p~netwr
  FROM vbak AS k
  INNER JOIN vbap AS p
    ON p~vbeln = k~vbeln
  LEFT OUTER JOIN makt AS t
    ON  t~matnr = p~matnr
    AND t~spras = @sy-langu
  WHERE k~erdat >= @lv_van
  INTO TABLE @DATA(lt_result).

Tabel-alias met ~ voor veldtoegang. INNER JOIN: alleen rijen die aan beide kanten bestaan; LEFT OUTER JOIN: alle linkerrijen, rechts leeg indien geen match. Ook beschikbaar: RIGHT OUTER JOIN, CROSS JOIN, en UNION/UNION ALL.

FOR ALL ENTRIES

Wil je databasedata ophalen voor de inhoud van een interne tabel, dan is er FOR ALL ENTRIES:

IF lt_orders IS NOT INITIAL.               " ← ABSOLUUT VERPLICHT
  SELECT matnr, maktx
    FROM makt
    FOR ALL ENTRIES IN @lt_orders
    WHERE matnr = @lt_orders-matnr
      AND spras = @sy-langu
    INTO TABLE @DATA(lt_teksten).
ENDIF.
De beruchtste ABAP-bug — is de interne tabel leeg, dan negeert de database de héle WHERE-clausule en selecteer je alle rijen van de tabel. Daarom altijd eerst de IS NOT INITIAL-check. Verder: FOR ALL ENTRIES dedupliceert het resultaat impliciet (geen dubbele rijen) en kan geen aggregaties gebruiken. In moderne code is een join of een CTE meestal beter.

Subqueries

SELECT matnr FROM mara
  WHERE EXISTS ( SELECT matnr FROM marc
                   WHERE matnr = mara~matnr AND werks = @p_werk )
  INTO TABLE @DATA(lt_matnr).

03Moderne SQL-expressies

Sinds 7.40/7.50 kan er steeds meer ín het SQL-statement — berekend op de database in plaats van in ABAP (zie code pushdown).

SELECT vbeln,
       netwr * @lv_koers                AS netwr_eur,     " rekenexpressie
       CASE WHEN netwr > 10000 THEN 'A'
            ELSE 'B' END              AS klasse,        " CASE
       CONCAT( vbeln, posnr )           AS sleutel,       " stringfuncties
       COALESCE( t~maktx, '(geen tekst)' ) AS tekst      " NULL-afhandeling
  FROM vbap ...

04Schrijven: INSERT, UPDATE, MODIFY, DELETE

Rechtstreeks schrijven doe je alleen op eigen Z-tabellen. SAP-standaardtabellen wijzig je vrijwel altijd via BAPI's — die bewaken de consistentie over alle gerelateerde tabellen.

INSERT ztabel FROM @ls_regel.              " sy-subrc 4 als key al bestaat
INSERT ztabel FROM TABLE @lt_regels.
UPDATE ztabel FROM @ls_regel.              " sy-subrc 4 als key niet bestaat
UPDATE ztabel SET status = 'X' WHERE erdat < @lv_datum.
MODIFY ztabel FROM @ls_regel.              " INSERT als nieuw, anders UPDATE
DELETE FROM ztabel WHERE status = 'X'.

Wijzigingen zijn pas definitief na COMMIT WORK; tot die tijd kan ROLLBACK WORK alles terugdraaien. Beveilig gelijktijdige toegang met locks.

05CDS-views

Core Data Services: datamodellen als broncode, met semantiek die verder gaat dan een klassieke database-view. Dé modelleerlaag van S/4HANA.

" Definitie in ADT (Eclipse), bestandstype "data definition"
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Verkooporders met klant'
define view entity ZI_SalesOrder
  as select from vbak
  association [0..1] to kna1 as _Klant
    on $projection.kunnr = _Klant.kunnr
{
  key vbak.vbeln,
      vbak.erdat,
      vbak.kunnr,
      @Semantics.amount.currencyCode: 'waerk'
      vbak.netwr,
      vbak.waerk,
      _Klant   // associatie mee-exposen
}

CDS is ook de basis van RAP en van embedded analytics. Meer diepgang op de moderne-ABAP-pagina.

06SQL-performance: de gouden regels

De vijf klassieke regels — plus wat er op HANA verandert.

  1. Houd de resultaatset klein — filter met WHERE op de database, niet achteraf in ABAP.
  2. Verstuur weinig data — veldlijst i.p.v. SELECT *, aggregaties op de database.
  3. Beperk het aantal rondgangen — geen SELECT in een LOOP (het klassieke "N+1"-probleem); gebruik joins, FOR ALL ENTRIES of één ophaling vooraf in een hashed tabel.
  4. Gebruik indexen — laat de WHERE aansluiten op de primaire sleutel of een (secundaire) index; velden waarop je met LIKE '%..' of NOT filtert gebruiken de index niet.
  5. Ontlast de database waar mogelijk — gebufferde tabellen (klein & stabiel, zie technische instellingen) niet omzeilen met BYPASSING BUFFER zonder reden.

Op HANA verschuift regel 5: reken- en aggregatiewerk mag juist wél naar de database (code pushdown), terwijl regels 1–4 onverminderd gelden. Meetgereedschap: SQL-trace (ST05) en runtime-analyse.