Sentencia MODIFY en ABAP: Modificar filas en tablas internas

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

La sentencia MODIFY se usa en ABAP para modificar filas existentes en tablas internas. Puede actualizar una sola fila (por indice o clave) o varias filas simultaneamente (con condicion WHERE). Si la fila no existe, MODIFY puede insertarla dependiendo de la variante.

Sintaxis

Existen varias variantes de la sentencia MODIFY:

1. Modificar fila por indice

MODIFY <tabla_interna> FROM <area_trabajo> INDEX <indice>
[TRANSPORTING <componente1> <componente2> ...].

2. Modificar o insertar fila por clave de tabla

MODIFY TABLE <tabla_interna> FROM <area_trabajo>
[TRANSPORTING <componente1> <componente2> ...].

3. Modificar multiples filas con condicion WHERE

MODIFY <tabla_interna> FROM <area_trabajo>
TRANSPORTING <componente1> [<componente2> ...]
WHERE <condicion>.

4. Modificar fila actual en LOOP

LOOP AT <tabla_interna> INTO <area_trabajo>.
" modificar <area_trabajo>
MODIFY <tabla_interna> FROM <area_trabajo>.
ENDLOOP.

Componentes

  • <tabla_interna>: La tabla cuyas filas seran modificadas.
  • <area_trabajo>: Una estructura con los nuevos valores. Debe ser compatible con el tipo de linea de la tabla.
  • INDEX <indice>: La posicion de la fila a modificar (solo para tablas standard y sorted).
  • TABLE: Identifica la variante con busqueda por clave. La fila se busca por la clave primaria.
  • TRANSPORTING <componentes>: Limita la modificacion a los componentes especificados. Los otros campos permanecen sin cambios.
  • WHERE <condicion>: Modifica todas las filas que cumplen la condicion.

Campos del sistema

Despues de un MODIFY se establecen los siguientes campos del sistema:

  • sy-subrc:

    • 0: Fila(s) modificada(s) con exito (o insertada con MODIFY TABLE).
    • 4: No se encontro fila coincidente (con INDEX o TABLE).
  • sy-tabix: Contiene el indice de la fila modificada (para operaciones de fila unica en tablas indexadas).

Funcionamiento segun variante

MODIFY … INDEX

Modifica la fila en la posicion de indice especificada. Todo el contenido del area de trabajo se copia a la fila (excepto con TRANSPORTING).

" Reemplazar completamente fila 3
MODIFY lt_data FROM ls_new_data INDEX 3.
" Cambiar solo ciertos campos en fila 3
MODIFY lt_data FROM ls_new_data INDEX 3 TRANSPORTING field1 field2.

MODIFY TABLE

Busca la fila por la clave primaria en el area de trabajo:

  • Encontrada: La fila se actualiza.
  • No encontrada: La fila se inserta (como INSERT).
" Buscar por clave y modificar o insertar
MODIFY TABLE lt_customers FROM ls_customer.

MODIFY … WHERE

Modifica todas las filas que cumplen la condicion WHERE. TRANSPORTING es obligatorio aqui.

" Modificar todas las filas con status = 'OLD'
MODIFY lt_orders FROM ls_update
TRANSPORTING status
WHERE status = 'OLD'.

MODIFY en LOOP (sin INDEX)

Dentro de un LOOP AT ... INTO, MODIFY puede usarse sin INDEX - entonces modifica automaticamente la fila actual.

LOOP AT lt_data INTO ls_data.
ls_data-field = 'Nuevo valor'.
MODIFY lt_data FROM ls_data.
ENDLOOP.

Mejor: Usa ASSIGNING en el loop para permitir modificaciones directas sin MODIFY.

Ejemplos

1. Modificar fila por indice

TYPES: BEGIN OF ty_product,
id TYPE i,
name TYPE string,
price TYPE p DECIMALS 2,
END OF ty_product.
DATA: lt_products TYPE STANDARD TABLE OF ty_product WITH EMPTY KEY,
ls_product TYPE ty_product.
" Llenar tabla
lt_products = VALUE #(
( id = 1 name = 'Laptop' price = '999.00' )
( id = 2 name = 'Raton' price = '29.99' )
( id = 3 name = 'Teclado' price = '79.00' )
).
" Reemplazar completamente fila 2
ls_product = VALUE #( id = 2 name = 'Raton Gaming' price = '59.99' ).
MODIFY lt_products FROM ls_product INDEX 2.
IF sy-subrc = 0.
WRITE: / 'Fila 2 modificada.'.
ENDIF.

2. Cambiar solo ciertos campos (TRANSPORTING)

" Cambiar solo el precio en fila 1
ls_product-price = '899.00'.
MODIFY lt_products FROM ls_product INDEX 1 TRANSPORTING price.
" Nombre e ID permanecen sin cambios
" Ver tambien: /es/blog/read-table-statement/
READ TABLE lt_products INTO ls_product INDEX 1.
WRITE: / 'Producto:', ls_product-name, 'Precio:', ls_product-price.
" Salida: Laptop 899.00

3. MODIFY TABLE (basado en clave)

TYPES: BEGIN OF ty_customer,
id TYPE i,
name TYPE string,
city TYPE string,
END OF ty_customer.
DATA: lt_customers TYPE HASHED TABLE OF ty_customer WITH UNIQUE KEY id,
ls_customer TYPE ty_customer.
" Llenar tabla
lt_customers = VALUE #(
( id = 1 name = 'Muller GmbH' city = 'Berlin' )
( id = 2 name = 'Schmidt AG' city = 'Munich' )
).
" Modificar cliente existente (ID 1 existe)
ls_customer = VALUE #( id = 1 name = 'Muller & Co. GmbH' city = 'Berlin' ).
MODIFY TABLE lt_customers FROM ls_customer.
IF sy-subrc = 0.
WRITE: / 'Cliente 1 modificado.'.
ENDIF.
" Insertar nuevo cliente (ID 3 no existe)
ls_customer = VALUE #( id = 3 name = 'Weber KG' city = 'Hamburgo' ).
MODIFY TABLE lt_customers FROM ls_customer.
WRITE: / 'Cantidad de clientes:', lines( lt_customers ). " Salida: 3

4. Modificar multiples filas con WHERE

TYPES: BEGIN OF ty_order,
order_id TYPE i,
status TYPE string,
amount TYPE p DECIMALS 2,
END OF ty_order.
DATA: lt_orders TYPE STANDARD TABLE OF ty_order WITH EMPTY KEY,
ls_update TYPE ty_order.
lt_orders = VALUE #(
( order_id = 1 status = 'NUEVO' amount = '100.00' )
( order_id = 2 status = 'NUEVO' amount = '250.00' )
( order_id = 3 status = 'ABIERTO' amount = '180.00' )
( order_id = 4 status = 'NUEVO' amount = '320.00' )
).
" Cambiar todos los pedidos con status 'NUEVO' a 'EN_PROCESO'
ls_update-status = 'EN_PROCESO'.
MODIFY lt_orders FROM ls_update
TRANSPORTING status
WHERE status = 'NUEVO'.
" Resultado: 3 filas modificadas (order_id 1, 2, 4)
LOOP AT lt_orders INTO DATA(ls_order).
WRITE: / ls_order-order_id, ls_order-status.
ENDLOOP.

5. MODIFY en LOOP con INTO

DATA: ls_prod TYPE ty_product.
" Aumentar todos los precios un 10%
LOOP AT lt_products INTO ls_prod.
ls_prod-price = ls_prod-price * '1.1'.
MODIFY lt_products FROM ls_prod.
ENDLOOP.

6. Mejor alternativa: LOOP con ASSIGNING

FIELD-SYMBOLS: <fs_prod> TYPE ty_product.
" Aumentar todos los precios un 10% - sin MODIFY
LOOP AT lt_products ASSIGNING <fs_prod>.
<fs_prod>-price = <fs_prod>-price * '1.1'.
ENDLOOP.
" Los cambios son efectivos inmediatamente, no se necesita MODIFY!

7. MODIFY TABLE con TRANSPORTING

" Cambiar solo la ciudad de un cliente (busqueda por clave)
ls_customer-id = 2. " Clave para la busqueda
ls_customer-city = 'Colonia'. " Nuevo valor
MODIFY TABLE lt_customers FROM ls_customer TRANSPORTING city.
IF sy-subrc = 0.
WRITE: / 'Ciudad del cliente 2 modificada.'.
ENDIF.

Comportamiento segun tipo de tabla

Tipo de tablaINDEXTABLEWHERE
STANDARD TABLESiSi (busqueda lineal)Si
SORTED TABLESiSi (busqueda binaria)Si
HASHED TABLENoSi (Hash-Lookup)Si

Importante para tablas sorted: Si modificas campos clave, esto puede violar el orden de clasificacion y causar un error de tiempo de ejecucion!

" Peligroso para SORTED TABLE con KEY id:
ls_customer-id = 999. " Cambiar campo clave
MODIFY TABLE lt_sorted_customers FROM ls_customer. " Puede causar dump!

Diferenciacion de otras sentencias

MODIFY vs. ASSIGNING en LOOP

AspectoMODIFY en LOOPASSIGNING
SintaxisMas codigoMas compacto
RendimientoMas lento (copiado)Mas rapido (acceso directo)
AplicacionCodigo legacyRecomendado
" Con MODIFY (obsoleto)
LOOP AT lt_data INTO ls_data.
ls_data-field = 'X'.
MODIFY lt_data FROM ls_data.
ENDLOOP.
" Con ASSIGNING (recomendado)
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-field = 'X'.
ENDLOOP.

MODIFY vs. INSERT y APPEND

  • MODIFY TABLE: Modifica fila existente O inserta nueva (Upsert).
  • INSERT: Solo inserta, falla si la clave existe.
  • APPEND: Siempre agrega al final de una tabla standard.

MODIFY vs. UPDATE (Base de datos)

  • MODIFY: Para tablas internas (en memoria).
  • UPDATE: Para tablas de base de datos (datos persistentes).

Para buscar una fila antes de modificar, ver READ TABLE.

Consejos de rendimiento

  1. ASSIGNING en lugar de MODIFY en LOOP: Evita LOOP ... INTO con MODIFY posterior. Usa ASSIGNING para acceso de escritura directo.

  2. TRANSPORTING para estructuras grandes: Si solo se modifican pocos campos, limita los datos a copiar con TRANSPORTING.

  3. WHERE para modificaciones masivas: MODIFY ... WHERE es mas eficiente que un loop manual con modificaciones individuales.

  4. No cambiar campos clave: En tablas sorted y hash, los campos clave no deben modificarse. En su lugar: eliminar fila e insertar nueva (ver APPEND o INSERT).

Notas importantes / Mejores practicas

  • Verifica sy-subrc despues de MODIFY con INDEX o TABLE para asegurar que se encontro la fila.
  • Prefiere ASSIGNING en LOOP AT para modificaciones directas - es mas eficiente y elegante que MODIFY.
  • Usa TRANSPORTING cuando solo ciertos campos deban modificarse.
  • MODIFY TABLE es un “Upsert” - inserta si la fila no existe.
  • Nunca modifiques campos clave directamente en tablas sorted o hash.
  • Con MODIFY ... WHERE, TRANSPORTING es obligatorio.
  • Esta sentencia MODIFY es para tablas internas. Para tablas de base de datos ver INSERT, UPDATE, DELETE.