ABAP INSERT, UPDATE, DELETE: Modificar tablas de base de datos

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

Las sentencias INSERT, UPDATE, DELETE y MODIFY son las herramientas centrales en ABAP para modificar datos en tablas de base de datos. Son parte de Open SQL y permiten insertar, actualizar y eliminar registros.

Importante: Los cambios en la base de datos solo se guardan permanentemente mediante COMMIT WORK. Hasta entonces, pueden revertirse con ROLLBACK WORK.

INSERT – Insertar nuevos registros

Sintaxis

" Insertar una fila
INSERT INTO <tabla_bd> VALUES <area_trabajo>.
" Insertar múltiples filas desde tabla interna
INSERT <tabla_bd> FROM TABLE <tabla_interna>
[ACCEPTING DUPLICATE KEYS].

Campos del sistema

  • sy-subrc:

    • 0: Inserción exitosa.
    • 4: La clave ya existe (duplicado).
  • sy-dbcnt: Número de filas insertadas.

Ejemplos

Insertar una fila

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: / 'Cliente creado exitosamente.'.
ELSE.
WRITE: / 'Error: El cliente ya existe.'.
ENDIF.

Insertar múltiples filas

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: / 'Filas insertadas:', sy-dbcnt.

Con ACCEPTING DUPLICATE KEYS

" Ignora duplicados, solo inserta filas nuevas
INSERT zcustomer FROM TABLE @lt_customers
ACCEPTING DUPLICATE KEYS.
IF sy-subrc = 4.
WRITE: / 'Algunas filas ya existían.'.
ENDIF.
WRITE: / 'Insertadas exitosamente:', sy-dbcnt.

UPDATE – Modificar registros existentes

Sintaxis

" Actualizar fila por clave (fila completa)
UPDATE <tabla_bd> FROM <area_trabajo>.
" Actualizar múltiples filas desde tabla interna
UPDATE <tabla_bd> FROM TABLE <tabla_interna>.
" Actualizar campos específicos con SET
UPDATE <tabla_bd>
SET <campo1> = <valor1>, <campo2> = <valor2>, ...
WHERE <condicion>.

Campos del sistema

  • sy-subrc:

    • 0: Al menos una fila actualizada.
    • 4: No se encontró ninguna fila coincidente.
  • sy-dbcnt: Número de filas actualizadas.

Ejemplos

Actualizar una fila (fila completa)

DATA: ls_customer TYPE zcustomer.
" Primero leer
SELECT SINGLE * FROM zcustomer
WHERE id = '1001'
INTO @ls_customer.
IF sy-subrc = 0.
" Modificar
ls_customer-city = 'Frankfurt'.
ls_customer-updated_at = sy-datum.
" Escribir de vuelta
UPDATE zcustomer FROM @ls_customer.
IF sy-subrc = 0.
WRITE: / 'Cliente actualizado.'.
ENDIF.
ENDIF.

Actualizar múltiples filas

DATA: lt_customers TYPE TABLE OF zcustomer.
" Cargar y modificar clientes
SELECT * FROM zcustomer
WHERE city = 'Berlin'
INTO TABLE @lt_customers.
LOOP AT lt_customers ASSIGNING FIELD-SYMBOL(<fs_cust>).
<fs_cust>-region = 'Este'.
ENDLOOP.
" Escribir todas las filas modificadas
UPDATE zcustomer FROM TABLE @lt_customers.
WRITE: / 'Filas actualizadas:', sy-dbcnt.

Con SET y WHERE (actualización masiva)

" Establecer región 'Este' para todos los clientes en Berlin
UPDATE zcustomer
SET region = 'Este',
updated_at = @sy-datum
WHERE city = 'Berlin'.
WRITE: / 'Filas actualizadas:', sy-dbcnt.

Calcular valores con SET

" Aumentar precios en 10%
UPDATE zproduct
SET price = price * '1.1',
updated_at = @sy-datum
WHERE category = 'ELECTRONICS'.
" Incrementar contador
UPDATE zcounter
SET count = count + 1
WHERE id = 'VISITOR'.

DELETE – Eliminar registros

Sintaxis

" Eliminar una fila por clave
DELETE <tabla_bd> FROM <area_trabajo>.
" Eliminar múltiples filas desde tabla interna
DELETE <tabla_bd> FROM TABLE <tabla_interna>.
" Eliminar filas con condición WHERE
DELETE FROM <tabla_bd> WHERE <condicion>.

Campos del sistema

  • sy-subrc:

    • 0: Al menos una fila eliminada.
    • 4: No se encontró ninguna fila coincidente.
  • sy-dbcnt: Número de filas eliminadas.

Ejemplos

Eliminar una fila

DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.
DELETE zcustomer FROM @ls_customer.
IF sy-subrc = 0.
WRITE: / 'Cliente eliminado.'.
ELSE.
WRITE: / 'Cliente no encontrado.'.
ENDIF.

Eliminar múltiples filas

DATA: lt_customers TYPE TABLE OF zcustomer.
" IDs de los clientes a eliminar
lt_customers = VALUE #(
( id = '1002' )
( id = '1003' )
).
DELETE zcustomer FROM TABLE @lt_customers.
WRITE: / 'Filas eliminadas:', sy-dbcnt.

Con condición WHERE (eliminación masiva)

" Eliminar todos los clientes inactivos
DELETE FROM zcustomer
WHERE status = 'INACTIVE'
AND last_order_date < '20200101'.
WRITE: / 'Filas eliminadas:', sy-dbcnt.
" ¡PRECAUCIÓN: Sin WHERE se eliminan TODAS las filas!
" DELETE FROM zcustomer. " ¡Elimina toda la tabla!

MODIFY – Insertar o actualizar (Upsert)

La sentencia MODIFY combina INSERT y UPDATE:

  • Si existe la clave → La fila se actualiza
  • Si no existe la clave → La fila se inserta

Sintaxis

" Una fila
MODIFY <tabla_bd> FROM <area_trabajo>.
" Múltiples filas
MODIFY <tabla_bd> FROM TABLE <tabla_interna>.

Campos del sistema

  • sy-subrc: Siempre 0 (excepto en errores de base de datos).
  • sy-dbcnt: Número de filas insertadas/actualizadas.

Ejemplos

DATA: ls_config TYPE zconfig.
ls_config-key = 'MAX_USERS'.
ls_config-value = '100'.
ls_config-updated_at = sy-datum.
" Inserta si no existe; actualiza si existe
MODIFY zconfig FROM @ls_config.
WRITE: / 'Configuración guardada.'.
DATA: lt_products TYPE TABLE OF zproduct.
lt_products = VALUE #(
( id = 'P001' name = 'Laptop' price = 999 ) " Nuevo o actualización
( id = 'P002' name = 'Ratón' price = 29 ) " Nuevo o actualización
( id = 'P003' name = 'Teclado' price = 79 ) " Nuevo o actualización
).
MODIFY zproduct FROM TABLE @lt_products.
WRITE: / 'Filas procesadas:', sy-dbcnt.

Comparación de sentencias

SentenciaAcciónCon clave existenteCon clave nueva
INSERTInsertarError (sy-subrc = 4)Insertar
UPDATEActualizarActualizarError (sy-subrc = 4)
DELETEEliminarEliminarError (sy-subrc = 4)
MODIFYUpsertActualizarInsertar

Control de transacciones

Los cambios de base de datos no se guardan permanentemente de inmediato. Primero se encuentran en un buffer de transacción:

" Realizar cambios
INSERT zcustomer FROM @ls_customer.
UPDATE zproduct SET price = 100 WHERE id = 'P001'.
DELETE FROM zlog WHERE created_at < '20240101'.
" Guardar cambios permanentemente
COMMIT WORK.
" O: Revertir cambios
" ROLLBACK WORK.

Ver COMMIT WORK / ROLLBACK WORK para detalles sobre control de transacciones.

Bloqueos (Locking)

Para accesos paralelos debe usar objetos de bloqueo SAP:

" Establecer bloqueo
CALL FUNCTION 'ENQUEUE_EZCUSTOMER'
EXPORTING
id = ls_customer-id
EXCEPTIONS
foreign_lock = 1
system_failure = 2
OTHERS = 3.
IF sy-subrc = 0.
" Realizar cambios
UPDATE zcustomer FROM @ls_customer.
COMMIT WORK.
" Liberar bloqueo
CALL FUNCTION 'DEQUEUE_EZCUSTOMER'
EXPORTING
id = ls_customer-id.
ELSE.
WRITE: / 'El registro está bloqueado.'.
ENDIF.

Consejos de rendimiento

  1. Preferir operaciones masivas:

    " Malo: INSERTs individuales en bucle
    LOOP AT lt_customers INTO DATA(ls_cust).
    INSERT zcustomer FROM @ls_cust.
    ENDLOOP.
    " Mejor: Un INSERT para todas las filas
    INSERT zcustomer FROM TABLE @lt_customers.
  2. UPDATE con SET para cambios masivos:

    " Malo: Cargar, modificar, escribir
    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.
    " Mejor: UPDATE directo con SET
    UPDATE zproduct SET status = 'ACTIVE' WHERE category = 'NEW'.
  3. ACCEPTING DUPLICATE KEYS con INSERT: Si se esperan duplicados, esto evita errores y es más eficiente que verificar previamente.

  4. Frecuencia de Commit: No ejecute COMMIT WORK después de cada operación individual, sino después de unidades lógicas.

Distinción: Tablas de base de datos vs. Tablas internas

AspectoTablas de base de datosTablas internas
SentenciasINSERT, UPDATE, DELETE, MODIFYAPPEND, MODIFY, DELETE, INSERT
PersistenciaPermanente (después de COMMIT)Solo en memoria
SintaxisINSERT <dbtab> FROM @waAPPEND wa TO itab
TransacciónCOMMIT/ROLLBACKNo aplicable

Notas importantes / Mejores prácticas

  • Siempre verificar sy-subrc después de operaciones de base de datos.
  • Usar COMMIT WORK para guardar cambios permanentemente.
  • Establecer bloqueos en cambios críticos para evitar conflictos de datos.
  • Preferir operaciones masivas (FROM TABLE) en lugar de bucles con operaciones individuales.
  • Tener cuidado con DELETE sin WHERE – ¡elimina todas las filas!
  • Usar MODIFY solo cuando realmente necesite comportamiento “Upsert”.
  • Probar operaciones críticas de base de datos primero con ROLLBACK WORK.
  • Usar SELECT para leer y verificar datos antes de modificar.