ABAP INSERT, UPDATE, DELETE: Datenbanktabellen ändern

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

Die Anweisungen INSERT, UPDATE, DELETE und MODIFY sind die zentralen Werkzeuge in ABAP, um Daten in Datenbanktabellen zu ändern. Sie sind Teil von Open SQL und ermöglichen das Einfügen, Aktualisieren und Löschen von Datensätzen.

Wichtig: Änderungen an der Datenbank werden erst durch COMMIT WORK dauerhaft gespeichert. Bis dahin können sie mit ROLLBACK WORK rückgängig gemacht werden.

INSERT – Neue Datensätze einfügen

Syntax

" Einzelne Zeile einfügen
INSERT INTO <dbtabelle> VALUES <arbeitsbereich>.
" Mehrere Zeilen aus interner Tabelle einfügen
INSERT <dbtabelle> FROM TABLE <interne_tabelle>
[ACCEPTING DUPLICATE KEYS].

Systemfelder

  • sy-subrc:

    • 0: Einfügen erfolgreich.
    • 4: Schlüssel existiert bereits (Duplikat).
  • sy-dbcnt: Anzahl der eingefügten Zeilen.

Beispiele

Einzelne Zeile einfügen

DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.
ls_customer-name = 'Müller GmbH'.
ls_customer-city = 'Berlin'.
ls_customer-created_at = sy-datum.
INSERT INTO zcustomer VALUES @ls_customer.
IF sy-subrc = 0.
WRITE: / 'Kunde erfolgreich angelegt.'.
ELSE.
WRITE: / 'Fehler: Kunde existiert bereits.'.
ENDIF.

Mehrere Zeilen einfügen

DATA: lt_customers TYPE TABLE OF zcustomer.
lt_customers = VALUE #(
( id = '1002' name = 'Schmidt AG' city = 'München' )
( id = '1003' name = 'Weber KG' city = 'Hamburg' )
( id = '1004' name = 'Fischer GmbH' city = 'Köln' )
).
INSERT zcustomer FROM TABLE @lt_customers.
WRITE: / 'Eingefügte Zeilen:', sy-dbcnt.

Mit ACCEPTING DUPLICATE KEYS

" Ignoriert Duplikate, fügt nur neue Zeilen ein
INSERT zcustomer FROM TABLE @lt_customers
ACCEPTING DUPLICATE KEYS.
IF sy-subrc = 4.
WRITE: / 'Einige Zeilen waren bereits vorhanden.'.
ENDIF.
WRITE: / 'Erfolgreich eingefügt:', sy-dbcnt.

UPDATE – Bestehende Datensätze ändern

Syntax

" Zeile über Schlüssel aktualisieren (komplette Zeile)
UPDATE <dbtabelle> FROM <arbeitsbereich>.
" Mehrere Zeilen aus interner Tabelle aktualisieren
UPDATE <dbtabelle> FROM TABLE <interne_tabelle>.
" Bestimmte Felder mit SET aktualisieren
UPDATE <dbtabelle>
SET <feld1> = <wert1>, <feld2> = <wert2>, ...
WHERE <bedingung>.

Systemfelder

  • sy-subrc:

    • 0: Mindestens eine Zeile aktualisiert.
    • 4: Keine passende Zeile gefunden.
  • sy-dbcnt: Anzahl der aktualisierten Zeilen.

Beispiele

Einzelne Zeile aktualisieren (komplette Zeile)

DATA: ls_customer TYPE zcustomer.
" Erst lesen
SELECT SINGLE * FROM zcustomer
WHERE id = '1001'
INTO @ls_customer.
IF sy-subrc = 0.
" Ändern
ls_customer-city = 'Frankfurt'.
ls_customer-updated_at = sy-datum.
" Zurückschreiben
UPDATE zcustomer FROM @ls_customer.
IF sy-subrc = 0.
WRITE: / 'Kunde aktualisiert.'.
ENDIF.
ENDIF.

Mehrere Zeilen aktualisieren

DATA: lt_customers TYPE TABLE OF zcustomer.
" Kunden laden und ändern
SELECT * FROM zcustomer
WHERE city = 'Berlin'
INTO TABLE @lt_customers.
LOOP AT lt_customers ASSIGNING FIELD-SYMBOL(<fs_cust>).
<fs_cust>-region = 'Ost'.
ENDLOOP.
" Alle geänderten Zeilen zurückschreiben
UPDATE zcustomer FROM TABLE @lt_customers.
WRITE: / 'Aktualisierte Zeilen:', sy-dbcnt.

Mit SET und WHERE (Massenupdate)

" Alle Kunden in Berlin auf Region 'Ost' setzen
UPDATE zcustomer
SET region = 'Ost',
updated_at = @sy-datum
WHERE city = 'Berlin'.
WRITE: / 'Aktualisierte Zeilen:', sy-dbcnt.

Werte berechnen mit SET

" Preise um 10% erhöhen
UPDATE zproduct
SET price = price * '1.1',
updated_at = @sy-datum
WHERE category = 'ELECTRONICS'.
" Zähler erhöhen
UPDATE zcounter
SET count = count + 1
WHERE id = 'VISITOR'.

DELETE – Datensätze löschen

Syntax

" Einzelne Zeile über Schlüssel löschen
DELETE <dbtabelle> FROM <arbeitsbereich>.
" Mehrere Zeilen aus interner Tabelle löschen
DELETE <dbtabelle> FROM TABLE <interne_tabelle>.
" Zeilen mit WHERE-Bedingung löschen
DELETE FROM <dbtabelle> WHERE <bedingung>.

Systemfelder

  • sy-subrc:

    • 0: Mindestens eine Zeile gelöscht.
    • 4: Keine passende Zeile gefunden.
  • sy-dbcnt: Anzahl der gelöschten Zeilen.

Beispiele

Einzelne Zeile löschen

DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.
DELETE zcustomer FROM @ls_customer.
IF sy-subrc = 0.
WRITE: / 'Kunde gelöscht.'.
ELSE.
WRITE: / 'Kunde nicht gefunden.'.
ENDIF.

Mehrere Zeilen löschen

DATA: lt_customers TYPE TABLE OF zcustomer.
" IDs der zu löschenden Kunden
lt_customers = VALUE #(
( id = '1002' )
( id = '1003' )
).
DELETE zcustomer FROM TABLE @lt_customers.
WRITE: / 'Gelöschte Zeilen:', sy-dbcnt.

Mit WHERE-Bedingung (Massenlöschung)

" Alle inaktiven Kunden löschen
DELETE FROM zcustomer
WHERE status = 'INACTIVE'
AND last_order_date < '20200101'.
WRITE: / 'Gelöschte Zeilen:', sy-dbcnt.
" VORSICHT: Ohne WHERE werden ALLE Zeilen gelöscht!
" DELETE FROM zcustomer. " Löscht die gesamte Tabelle!

MODIFY – Einfügen oder Aktualisieren (Upsert)

Die MODIFY-Anweisung kombiniert INSERT und UPDATE:

  • Existiert der Schlüssel → Zeile wird aktualisiert
  • Existiert der Schlüssel nicht → Zeile wird eingefügt

Syntax

" Einzelne Zeile
MODIFY <dbtabelle> FROM <arbeitsbereich>.
" Mehrere Zeilen
MODIFY <dbtabelle> FROM TABLE <interne_tabelle>.

Systemfelder

  • sy-subrc: Immer 0 (außer bei Datenbankfehlern).
  • sy-dbcnt: Anzahl der eingefügten/aktualisierten Zeilen.

Beispiele

DATA: ls_config TYPE zconfig.
ls_config-key = 'MAX_USERS'.
ls_config-value = '100'.
ls_config-updated_at = sy-datum.
" Fügt ein, wenn nicht vorhanden; aktualisiert, wenn vorhanden
MODIFY zconfig FROM @ls_config.
WRITE: / 'Konfiguration gespeichert.'.
DATA: lt_products TYPE TABLE OF zproduct.
lt_products = VALUE #(
( id = 'P001' name = 'Laptop' price = 999 ) " Neu oder Update
( id = 'P002' name = 'Maus' price = 29 ) " Neu oder Update
( id = 'P003' name = 'Tastatur' price = 79 ) " Neu oder Update
).
MODIFY zproduct FROM TABLE @lt_products.
WRITE: / 'Verarbeitete Zeilen:', sy-dbcnt.

Vergleich der Anweisungen

AnweisungAktionBei existierendem SchlüsselBei neuem Schlüssel
INSERTEinfügenFehler (sy-subrc = 4)Einfügen
UPDATEAktualisierenAktualisierenFehler (sy-subrc = 4)
DELETELöschenLöschenFehler (sy-subrc = 4)
MODIFYUpsertAktualisierenEinfügen

Transaktionssteuerung

Datenbankänderungen werden nicht sofort dauerhaft gespeichert. Sie befinden sich zunächst in einem Transaktionspuffer:

" Änderungen durchführen
INSERT zcustomer FROM @ls_customer.
UPDATE zproduct SET price = 100 WHERE id = 'P001'.
DELETE FROM zlog WHERE created_at < '20240101'.
" Änderungen dauerhaft speichern
COMMIT WORK.
" ODER: Änderungen rückgängig machen
" ROLLBACK WORK.

Siehe COMMIT WORK / ROLLBACK WORK für Details zur Transaktionssteuerung.

Sperren (Locking)

Bei parallelen Zugriffen sollten Sie SAP-Sperrobjekte verwenden:

" Sperre setzen
CALL FUNCTION 'ENQUEUE_EZCUSTOMER'
EXPORTING
id = ls_customer-id
EXCEPTIONS
foreign_lock = 1
system_failure = 2
OTHERS = 3.
IF sy-subrc = 0.
" Änderungen durchführen
UPDATE zcustomer FROM @ls_customer.
COMMIT WORK.
" Sperre freigeben
CALL FUNCTION 'DEQUEUE_EZCUSTOMER'
EXPORTING
id = ls_customer-id.
ELSE.
WRITE: / 'Datensatz ist gesperrt.'.
ENDIF.

Performance-Tipps

  1. Massenoperationen bevorzugen:

    " Schlecht: Einzelne INSERTs in Schleife
    LOOP AT lt_customers INTO DATA(ls_cust).
    INSERT zcustomer FROM @ls_cust.
    ENDLOOP.
    " Besser: Ein INSERT für alle Zeilen
    INSERT zcustomer FROM TABLE @lt_customers.
  2. UPDATE mit SET für Massenänderungen:

    " Schlecht: Laden, ändern, zurückschreiben
    SELECT * FROM zproduct INTO TABLE @DATA(lt_products).
    LOOP AT lt_products ASSIGNING FIELD-SYMBOL(<fs>).
    <fs>-status = 'ACTIVE'.
    ENDLOOP.
    UPDATE zproduct FROM TABLE @lt_products.
    " Besser: Direktes UPDATE mit SET
    UPDATE zproduct SET status = 'ACTIVE' WHERE category = 'NEW'.
  3. ACCEPTING DUPLICATE KEYS bei INSERT: Wenn Duplikate erwartet werden, vermeidet dies Fehler und ist effizienter als vorheriges Prüfen.

  4. Commit-Häufigkeit: Führen Sie COMMIT WORK nicht nach jeder Einzeloperation aus, sondern nach logischen Einheiten.

Abgrenzung: Datenbanktabellen vs. Interne Tabellen

AspektDatenbanktabellenInterne Tabellen
AnweisungenINSERT, UPDATE, DELETE, MODIFYAPPEND, MODIFY, DELETE, INSERT
PersistenzDauerhaft (nach COMMIT)Nur im Arbeitsspeicher
SyntaxINSERT <dbtab> FROM @waAPPEND wa TO itab
TransaktionCOMMIT/ROLLBACKNicht anwendbar

Wichtige Hinweise / Best Practice

  • Prüfen Sie immer sy-subrc nach Datenbankoperationen.
  • Verwenden Sie COMMIT WORK um Änderungen dauerhaft zu speichern.
  • Setzen Sie Sperren bei kritischen Änderungen, um Datenkonflikte zu vermeiden.
  • Bevorzugen Sie Massenoperationen (FROM TABLE) statt Schleifen mit Einzeloperationen.
  • Seien Sie vorsichtig mit DELETE ohne WHERE – es löscht alle Zeilen!
  • Verwenden Sie MODIFY nur, wenn Sie tatsächlich ein “Upsert”-Verhalten benötigen.
  • Testen Sie kritische Datenbankoperationen immer zuerst mit ROLLBACK WORK.
  • Nutzen Sie SELECT um Daten vor dem Ändern zu lesen und zu prüfen.