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ügenINSERT INTO <dbtabelle> VALUES <arbeitsbereich>.
" Mehrere Zeilen aus interner Tabelle einfügenINSERT <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 einINSERT 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 aktualisierenUPDATE <dbtabelle> FROM TABLE <interne_tabelle>.
" Bestimmte Felder mit SET aktualisierenUPDATE <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 lesenSELECT 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 ändernSELECT * 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ückschreibenUPDATE zcustomer FROM TABLE @lt_customers.
WRITE: / 'Aktualisierte Zeilen:', sy-dbcnt.Mit SET und WHERE (Massenupdate)
" Alle Kunden in Berlin auf Region 'Ost' setzenUPDATE zcustomer SET region = 'Ost', updated_at = @sy-datum WHERE city = 'Berlin'.
WRITE: / 'Aktualisierte Zeilen:', sy-dbcnt.Werte berechnen mit SET
" Preise um 10% erhöhenUPDATE zproduct SET price = price * '1.1', updated_at = @sy-datum WHERE category = 'ELECTRONICS'.
" Zähler erhöhenUPDATE zcounter SET count = count + 1 WHERE id = 'VISITOR'.DELETE – Datensätze löschen
Syntax
" Einzelne Zeile über Schlüssel löschenDELETE <dbtabelle> FROM <arbeitsbereich>.
" Mehrere Zeilen aus interner Tabelle löschenDELETE <dbtabelle> FROM TABLE <interne_tabelle>.
" Zeilen mit WHERE-Bedingung löschenDELETE 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 Kundenlt_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öschenDELETE 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 ZeileMODIFY <dbtabelle> FROM <arbeitsbereich>.
" Mehrere ZeilenMODIFY <dbtabelle> FROM TABLE <interne_tabelle>.Systemfelder
sy-subrc: Immer0(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 vorhandenMODIFY 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
| Anweisung | Aktion | Bei existierendem Schlüssel | Bei neuem Schlüssel |
|---|---|---|---|
INSERT | Einfügen | Fehler (sy-subrc = 4) | Einfügen |
UPDATE | Aktualisieren | Aktualisieren | Fehler (sy-subrc = 4) |
DELETE | Löschen | Löschen | Fehler (sy-subrc = 4) |
MODIFY | Upsert | Aktualisieren | Einfügen |
Transaktionssteuerung
Datenbankänderungen werden nicht sofort dauerhaft gespeichert. Sie befinden sich zunächst in einem Transaktionspuffer:
" Änderungen durchführenINSERT zcustomer FROM @ls_customer.UPDATE zproduct SET price = 100 WHERE id = 'P001'.DELETE FROM zlog WHERE created_at < '20240101'.
" Änderungen dauerhaft speichernCOMMIT 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 setzenCALL 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
-
Massenoperationen bevorzugen:
" Schlecht: Einzelne INSERTs in SchleifeLOOP AT lt_customers INTO DATA(ls_cust).INSERT zcustomer FROM @ls_cust.ENDLOOP." Besser: Ein INSERT für alle ZeilenINSERT zcustomer FROM TABLE @lt_customers. -
UPDATE mit SET für Massenänderungen:
" Schlecht: Laden, ändern, zurückschreibenSELECT * 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 SETUPDATE zproduct SET status = 'ACTIVE' WHERE category = 'NEW'. -
ACCEPTING DUPLICATE KEYS bei INSERT: Wenn Duplikate erwartet werden, vermeidet dies Fehler und ist effizienter als vorheriges Prüfen.
-
Commit-Häufigkeit: Führen Sie
COMMIT WORKnicht nach jeder Einzeloperation aus, sondern nach logischen Einheiten.
Abgrenzung: Datenbanktabellen vs. Interne Tabellen
| Aspekt | Datenbanktabellen | Interne Tabellen |
|---|---|---|
| Anweisungen | INSERT, UPDATE, DELETE, MODIFY | APPEND, MODIFY, DELETE, INSERT |
| Persistenz | Dauerhaft (nach COMMIT) | Nur im Arbeitsspeicher |
| Syntax | INSERT <dbtab> FROM @wa | APPEND wa TO itab |
| Transaktion | COMMIT/ROLLBACK | Nicht anwendbar |
Wichtige Hinweise / Best Practice
- Prüfen Sie immer
sy-subrcnach Datenbankoperationen. - Verwenden Sie
COMMIT WORKum Ä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
MODIFYnur, wenn Sie tatsächlich ein “Upsert”-Verhalten benötigen. - Testen Sie kritische Datenbankoperationen immer zuerst mit
ROLLBACK WORK. - Nutzen Sie
SELECTum Daten vor dem Ändern zu lesen und zu prüfen.