Exchange Currency

jueves, 14 de abril de 2016

Bucles en SAP ABAP

Buen día a todos, gracias a los usuarios que me han dejado comentarios ya que son de gran ayuda. En esta oportunidad quiero hablarles sobre los bucles que podemos utilizar en el lenguaje ABAP, ya que a veces se nos presentan problemas de rendimiento y no sabemos el porqué.


Bucles en SAP ABAP

En un bucle, un bloque de instrucciones se ejecuta varias veces en la serie.  Existen cuatro tipos de bucles en ABAP:

  • Los bucles sentencia DO (principalmente para los bucles incondicionales)
  • Los bucles WHILE (principalmente para los bucles condicionales)
  • Los bucles instrucción SELECT (bucle a través de los datos de base de datos)
  • Los bucles sentencia LOOP (bucle en las tablas internas)

Bucle DO - ENDDO “Bucle incondicional” 


Ejecución de sentencias indefinidamente hasta que se procese la sentencia EXIT, STOP o REJECT.


Sintaxis:

 
DO [ TIMES ] [ VARYING FROM NEXT ]

ENDDO.


La sentencia DO sin cláusulas ejecuta el bloque de sentencias indefinidamente, o hasta que se procese una sentencia EXIT, STOP o REJECT. Para limitar el número de pasos de un bucle se puede utilizar la opción TIMES. Puede ser un literal o una variable. Si es 0 o negativo, el sistema no procesará el bucle.


La cláusula ENDDO es obligatoria (marca el fin del bloque de sentencias). La variable SY-INDEX contiene el número de veces que el bucle ha sido ejecutado.


Utilizando la opción VARYING se pueden ir asignando valores a una variable a partir de un conjunto de campos del mismo tipo y longitud de memoria por cada paso de bucle. En una sentencia DO se pueden utilizar varias opciones VARYING.


Ejemplo:

 
DO.

WRITE: / SY-INDEX – Inicio:’, (3) SY-INDEX.

IF SY-INDEX = 10.

EXIT.

ENDIF.

WRITE: ‘Fin:’, (3) SY-INDEX.

ENDDO.


Otro ejemplo simple de un bucle DO:


DO.

WRITE sy-index.

IF sy-index = 3.

EXIT.

ENDIF.

ENDDO.


La salida de la lista es la siguiente: 1, 2, 3.


El bucle se procesa tres veces. Aquí, el procesamiento pasa a través del bucle de tres veces y luego sale ejecutando la instrucción EXIT.


Ejemplo de dos bucles anidados con la adición TIEMPOS: 


DO 2 TIMES.

WRITE sy-index.

SKIP. “salta 1 línea.

DO 3 TIMES.

WRITE sy-index.

ENDDO.

SKIP.

ENDDO.


La salida de la lista es la siguiente: Primer DO 1, Segundo DO 1 2 3, Primer DO 2, Segundo DO 1 2 3.


El bucle exterior se procesa dos veces. Cada vez que se procesa el bucle exterior, el bucle interno se procesa en tres ocasiones. Debemos tener en cuenta que el campo del sistema sy-index contiene el número de bucle que pasa por cada bucle individual.


Bucle WHILE – ENDWHILE “Bucles condicional”


Se utiliza para repetir un bloque de instrucciones durante el tiempo que una determinada condición es verdadera, utilice la siguiente estructura de control:

Sintaxis:


WHILE log_exp o [ VARY FROM NEXT ].

[statemaent_block]

ENDWHILE. 


log_exp puede ser cualquier expresión lógica. El bloque de instrucciones entre WHILE y ENDWHILE se repite mientras la condición es verdadera o hasta que una declaración de terminación, tales como cierre o detenga ocurre. El campo del sistema sy-index contiene el número de bucle pasa.


El sistema procesa el bloque de sentencias hasta que se cumpla la condición o hasta que el sistema procesa una sentencia EXIT, STOP o REJECT. Para condición se puede utilizar cualquier expresión lógica. El campo del sistema SY-INDEX contiene el número de veces que el bucle ha sido ejecutado. El sistema permite anidar sentencias WHILE, así como combinarlas con otras sentencias de bucle.


La opción VARY actúa de la misma forma en que actúa la opción VARYING en la sentencia DO. Al igual en la sentencia DO, se puede utilizar más de una opción VARY en una sentencia WHILE.


Ejemplo:


DATA: SEARCH_ME TYPE I,

MIN TYPE I VALUE 0,

MAX TYPE I VALUE 1000,

TRIES TYPE I,

NUMBER TYPE I.

SEARCH_ME = 23.

WHILE NUMBER SEARCH_ME.

ADD 1 TO TRIES.

NUMBER = ( MIN + MAX ) / 2.

IF NUMBER > SEARCH_ME.

MAX = NUMBER – 1.

ELSE.

MIN = NUMBER + 1.

ENDIF.
ENDWHILE. 


Para la utilización y explicación de los Bucles Select y Loop, utilizaremos Tablas internas, por ello les hablare un poco sobre ellas:


Las tablas internas sirven para almacenar información extraída de la base de datos. En este ejemplo voy a declarar una tabla interna de la siguiente forma:


* Tabla de vuelos

DATA:

  BEGIN OF i_vuelos OCCURS 0,

    carrid LIKE sflight-carrid, "Código de aerolínea

    connid LIKE sflight-connid, "Número de vuelo

    fldate LIKE sflight-fldate, "Fecha de vuelo

    planetype LIKE sflight-planetype, "Tipo de avión

  END OF i_vuelos.


Bucle SELECT - ENDSELECT “Bucle a través de los datos de base de datos”


Esta sentencia realiza una lectura lineal de los datos de las tablas de la base de datos y los asigna directamente a los campos de nuestra tabla interna. Pero atención, para que queden almacenados sobre la tabla interna para cada registro seleccionado debemos utilizar la sentencia APPEND. Así, haremos añadiremos los registros a nuestra tabla interna.


SELECT * FROM sflight WHERE carrid IN s_carrid.

  i_vuelos-carrid = sflight-carrid.

  i_vuelos-connid = sflight-connid.

  i_vuelos-fldate = sflight-fldate.

  i_vuelos-planetype = sflight-planetype.

  APPEND i_vuelos. CLEAR i_vuelos.

ENDSELECT.



El símbolo (*) le indica a SAP que debe guardar en memoria absolutamente todos los valores de todos los campos de cada registro de la tabla SAP. 


La cláusula WHERE nos permite indicar el filtro de selección. En este caso utilizamos como filtro el rango de códigos de aerolíneas. De la tabla sflight sólo recuperaremos aquellos registros que cumplan con la condición indicada en el WHERE. 


Seguidamente asignamos a cada campo de la tabla interna el valor del campo de la tabla SAP, dejándolo a nivel de la cabecera de la tabla interna.


Finalmente, guardamos el registro en nuestra tabla interna mediante la sentencia APPEND.
Con la sentencia CLEAR limpiamos la cabecera y la dejamos lista para el siguiente registro.


La sentencia SELECT...ENDSELECT irá pasando uno a uno por cada uno de los registros que cumplan la condición de la cláusula WHERE y los irá almacenando gracias a la sentencia APPEND dentro de nuestra tabla interna.


El mayor inconveniente de trabajar con la forma SELECT...ENDSELECT es que la lectura se hace linealmente, es decir, SAP debe pasar por cada uno de los registros individualmente hasta llegar al final. Esto hace que la búsqueda de datos sea muy ineficiente en términos de rendimiento y alarga innecesariamente el tiempo de ejecución del programa.


Una forma de mejorar el rendimiento sería no utilizar la cláusula (*) sino indicar específicamente los campos que necesitamos llenar. He aquí donde radica la eficiencia de los programas Estándar que utilizan en su mayoría SELECT...ENDSELECT.


SELECT carrid connid fldate planetype FROM sflight

INTO (i_vuelos-carrid, i_vuelos-connid, i_vuelos-fldate, i_vuelos-planetype)

WHERE carrid IN s_carrid.

APPEND i_vuelos. CLEAR i_vuelos.

ENDSELECT.



Al no usar todos los campos mejoramos el rendimiento y con la cláusulo INTO asignamos directamente el valor al campo de la tabla interna.


Nota: En las mejores prácticas de SAP se indica evitar el uso del SELECT...ENDSELECT, reemplazándolo por el bucle LOOP.


Otra forma de sentencia select, ojo no son bucles
.

Existe otra forma de la sentencia SELECT mucho más eficiente nos permite almacenar los datos en la tabla interna sin necesidad de utilizar la sentencia APPEND. El mismo efecto que en el caso anterior lo obtendríamos usando...



SELECT * FROM sflight

INTO CORRESPONDING FIELDS OF TABLE i_vuelos

WHERE carrid IN s_carrid.



Seguimos utilizando el valor (*) para leer todos los campos.


La claúsula INTO CORRESPONDING FIELDS OF TABLE compara el nombre del campo de la tabla de SAP con cada nombre de la tabla interna. Si encuentra coincidencia le asigna su valor correspondiente. Por eso, es tan importante que el nombre de los campos de una tabla interna sean iguales al nombre de los campos de una tabla SAP. De lo contrario, esta forma no se puede utilizar. Se mantiene la cláusula WHERE. Se elimina la sentencia APPEND ya que la lectura deja de ser secuencial sino en bloques. Es decir, SAP ya no tiene que recorrer uno a uno todos los registros, sino que toma el bloque de registros que coinciden con la condición determinada a través de la cláusula WHERE y lo asigna en bloque a la tabla interna.


Y aún, otra variación que podemos utilizar sería:


SELECT carrid connid fldate planetype FROM sflight

INTO TABLE i_vuelos

WHERE carrid IN s_carrid.


Esta forma es todavía más eficiente ya que:


Evita el uso de (*) y en su lugar sólo toma el valor de los campos que nos interesa (carrid, connid, fldate y planetype). 


La cláusula INTO TABLE asigna estos cuatro campos a los cuatro primeros campos de la tabla interna. Así que, cuidado, el orden en que se hayan declarado estos campos en la tabla interna es importante. Aquí no hay asignación por nombre de campo, sino por posición, el valor del campo carrid de la tabla sflight se asignará al primer campo de la tabla interna, el valor del campo connid de la tabla sflight se asignará al segundo campo de la tabla interna, y así sucesivamente. Aquí ya no es tan importante el nombre de los campos de la tabla interna, pero sí la longitud y el tipo de esos campos. Si no lo tenemos cuenta nuestro programa acabar abruptamente con dump breve. 


Bucle LOOP- ENDLOOP “Bucle en las tablas internas”


Esta sentencia nos permite recorrer uno a uno todos los registros que hemos guardado previamente en nuestra tabla interna. La forma en que la tratamos varía dependiendo de si hemos declarado nuestra tabla interna con cabecera o sin cabecera.


La sentencia loop...endloop en tablas internas con cabecera


No necesitan de ninguna variable adicional. Simplemente llamamos a nuestra tabla interna mediante la sentencia loop...endloop. En ese mismo momento, todos los registros de cada línea se cargan sobre la cabecera de la propia tabla interna.


LOOP AT <tabla_interna>.

*   Acción sobre <tabla_interna>

ENDLOOP.



La sentencia loop...endloop en tablas internas sin cabecera


Necesitan de una variable estructura adicional donde se contenga el valor de cada registro de la tabla interna. Al hacer una llamada loop...endloop, el valor del registro por el que pasa se ha de traspasar a esta variable adicional.


LOOP AT <tabla_interna> into <estructura>.

*    Acción sobre <estructura>

ENDLOOP. 


La sentencia write


Sirve para "escribir" los datos de cada uno de los registros de nuestra tabla interna en la pantalla del ordenador y que sean visibles por el usuario. Por ejemplo, dentro de nuestra sentencia loop...enloop, cada uno de los registros se irían escribiendo uno a uno en pantalla gracias a la sentencia write.


LOOP AT <tabla_interna>.

  write: <tabla_interna>

ENDLOOP.


Sin embargo, si lo que queremos no es escribir todos los campos de cada registro, sino sólo algunos campos de cada registro entonces lo haríamos del siguiente modo: 


LOOP AT <tabla_interna>.

  write: / <tabla_interna>-campo1,

          <tabla_interna>-campo2.

          <tabla_interna>-campo3.

  ...

ENDLOOP. 


La clásula "/" indica a SAP que todos los registros que siguen a continuación se han de escribir en una línea diferente. De otro modo, cada registro se montaría uno encima de otro y sólo se vería impreso en pantalla el último registro.

Por supuesto, la sentencia Write tiene muchas y variadas cláusulas. Algunas de ellas son:

  • Write <variable> DD/MM/YYYY: formatea las variables de tipo fecha para que el campo de salida se vea en la forma día/mes/año.
  • Write <variable> unit <unidad>: si el campo <variable> es una cantidad se imprimirá en pantalla según la unidad definida.
  • Write <variable> left-justified | centered | right-justified: escribe el campo a la izquierda, derecha o centro.
  • Write <variable> no-zero: elimina los ceros a la izquierda del campo.

NOTA: Algo que deben evitar totalmente es el uso de Select Single dentro de un LOOP esto afectara rotundamente el rendimiento de su programa. Pueden intentarlo como prueba.


Si tienen alguna duda, comentario o aporte que realizar estaré muy agradecido.

0 comentarios:

Dí lo que piensas...

Technology

Publicidad