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 filaINSERT INTO <tabla_bd> VALUES <area_trabajo>.
" Insertar múltiples filas desde tabla internaINSERT <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 nuevasINSERT 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 internaUPDATE <tabla_bd> FROM TABLE <tabla_interna>.
" Actualizar campos específicos con SETUPDATE <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 leerSELECT 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 clientesSELECT * 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 modificadasUPDATE 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 BerlinUPDATE 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 contadorUPDATE zcounter SET count = count + 1 WHERE id = 'VISITOR'.DELETE – Eliminar registros
Sintaxis
" Eliminar una fila por claveDELETE <tabla_bd> FROM <area_trabajo>.
" Eliminar múltiples filas desde tabla internaDELETE <tabla_bd> FROM TABLE <tabla_interna>.
" Eliminar filas con condición WHEREDELETE 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 eliminarlt_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 inactivosDELETE 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 filaMODIFY <tabla_bd> FROM <area_trabajo>.
" Múltiples filasMODIFY <tabla_bd> FROM TABLE <tabla_interna>.Campos del sistema
sy-subrc: Siempre0(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 existeMODIFY 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
| Sentencia | Acción | Con clave existente | Con clave nueva |
|---|---|---|---|
INSERT | Insertar | Error (sy-subrc = 4) | Insertar |
UPDATE | Actualizar | Actualizar | Error (sy-subrc = 4) |
DELETE | Eliminar | Eliminar | Error (sy-subrc = 4) |
MODIFY | Upsert | Actualizar | Insertar |
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 cambiosINSERT zcustomer FROM @ls_customer.UPDATE zproduct SET price = 100 WHERE id = 'P001'.DELETE FROM zlog WHERE created_at < '20240101'.
" Guardar cambios permanentementeCOMMIT 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 bloqueoCALL 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
-
Preferir operaciones masivas:
" Malo: INSERTs individuales en bucleLOOP AT lt_customers INTO DATA(ls_cust).INSERT zcustomer FROM @ls_cust.ENDLOOP." Mejor: Un INSERT para todas las filasINSERT zcustomer FROM TABLE @lt_customers. -
UPDATE con SET para cambios masivos:
" Malo: Cargar, modificar, escribirSELECT * 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 SETUPDATE zproduct SET status = 'ACTIVE' WHERE category = 'NEW'. -
ACCEPTING DUPLICATE KEYS con INSERT: Si se esperan duplicados, esto evita errores y es más eficiente que verificar previamente.
-
Frecuencia de Commit: No ejecute
COMMIT WORKdespués de cada operación individual, sino después de unidades lógicas.
Distinción: Tablas de base de datos vs. Tablas internas
| Aspecto | Tablas de base de datos | Tablas internas |
|---|---|---|
| Sentencias | INSERT, UPDATE, DELETE, MODIFY | APPEND, MODIFY, DELETE, INSERT |
| Persistencia | Permanente (después de COMMIT) | Solo en memoria |
| Sintaxis | INSERT <dbtab> FROM @wa | APPEND wa TO itab |
| Transacción | COMMIT/ROLLBACK | No aplicable |
Notas importantes / Mejores prácticas
- Siempre verificar
sy-subrcdespués de operaciones de base de datos. - Usar
COMMIT WORKpara 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
MODIFYsolo cuando realmente necesite comportamiento “Upsert”. - Probar operaciones críticas de base de datos primero con
ROLLBACK WORK. - Usar
SELECTpara leer y verificar datos antes de modificar.