Vous êtes sur la page 1sur 31

Tablas internas

Tablas internas
1.- Introduccin
El objeto de la implementacin de las tablas internas en SAP es el de guardar datos de cualquier Base de Datos del sistema con la intencin de poder operar con ellos sin la necesidad de tener que ir accediendo a la misma con cada consulta que hagamos. Con ello conseguimos guardar una coleccin de los datos accedidos en memoria. Con anterioridad a la versin 3.0 de SAP, las tablas internas representaban tablas de bases de datos guardadas internamente en memoria, y las lneas de stas consistan en estructuras planas. No obstante, y tras la citada versin, dicho tipo de lnea pas a ser arbitrario. El espectro de rangos de tablas internas de arrays de campos elementales se ampli llegando hasta objetos de datos dinmicos altamente complejos donde las lneas o los componentes de stas podan llegar a ser incluso ms tablas internas en s mismos. La caracterstica ms reseable de las tablas internas puede que sea que para cualquier tipo de lnea dado, se puede grabar un nmero ilimitado1 de lneas en memoria. Dicho nmero de lneas es determinado en tiempo de ejecucin del programa. Por otro lado, las tablas internas estn gestionadas implcitamente por el entorno de ejecucin del programa ABAP que la utiliza. Este lenguaje de programacin implementa una serie de sentencias que permiten al usuario trabajar con ellas y manejar objetos de datos dinmicos complejos. En la siguiente figura podemos ver un ejemplo sencillo de implementacin y uso de una tabla interna:
DATA: BEGIN OF i_tab OCCURS 0, nombre(20) TYPE c, direccion(20) TYPE c, telefono(10) TYPE i, dni TYPE i. DATA: END OF i_tab. SELECTION-SCREEN: BEGIN OF BLOCK b1. PARAMETERS: p_nombre(20) TYPE c, p_direcc(20) TYPE c, p_telef(10) TYPE i, p_dni(10) TYPE i. SELECTION-SCREEN: END OF BLOCK b1. START-OF-SELECTION. i_tab-nombre = p_nombre. i_tab-direccion = p_direcc. i_tab-telefono = p_telef. i_tab-dni = p_dni.

Como puede observarse, su manejo en nada difiere de lo que ya conocemos. En el ejemplo que nos ocupa, el programa bastante rudimentario, por lo dems-, se limita a pedir unos datos por pantalla y a asignarlos a la tabla interna en el comienzo de la seleccin.

Por supuesto, el nmero de lneas de una tabla interna vendr restringido por la propia memoria fsica instalada en el sistema. En teora, una tabla interna puede llegar a alcanzar hasta los dos Gigabytes. De todos modos, la memoria no suele estar reservada en su totalidad al uso de una sola tabla interna. De hecho, en una plataforma de 32 bits no podremos tener tablas internas de ms de 500 MB. Con tablas hashed el nmero de lneas est limitado a dos millones.

Tablas internas

2.- Tipos de tablas internas


El tipo de tabla interna determina cmo es gestionada por el sistema internamente, y cmo es accedida en nuestro programa ABAP. El decidir por qu tipo de tabla interna decantarnos depende del tipo de operaciones que queramos hacer con la ella y la frecuencia con que queramos repetirlas. Segn esto, tenemos:

2.1.- Tablas estndar


Para la definicin de tablas estndar usamos la clusula STANDARD TABLE. Las lneas individuales de una tabla estndar son gestionadas internamente por un ndice lgico. Cuando rellenamos una tabla estndar, se van aadiendo nuevas lneas al final de la misma o en ciertas posiciones. Podemos realizar la lectura bien mediante la especificacin de una clave o bien mediante un ndice. Si accedemos a travs de ste ltimo, la lgica del programa debe conocer en todo momento qu lneas pertenecen al ndice especificado.

2.2.- Tablas sorted


Para la definicin de tablas sorted usaremos la clusula SORTED TABLE. Como en el caso de las tablas estndar, las tablas sorted son gestionadas por un ndice lgico. De todos modos, las tablas sorted difieren de las estndar en que sus entradas estn siempre dispuestas en orden ascendente de acuerdo con una clave de la tabla. El acceso a tablas sorted se hace de igual modo que para las tablas estndar.

2.3.- Tablas hashed


Para la definicin de este tipo de tablas hemos de usar la sentencia HASHED TABLE. En este caso, el orden de las entradas no est gestionado por un ndice lgico; en lugar de eso, las entradas de la tabla se encuentran alamcenadas en memoria sin orden concreto, y se manejan a travs de un algoritmo hash. La posicin de una entrada es calculada directamente a travs de una funcin hash. Con tablas hashed el acceso basado en ndices no es posible.

2.4.- Jerarqua de tablas

Tablas interna
Tablas indexadas

Tablas estndar

Tablas

Tablas hashed

Tablas internas

2.5.- Acceso a los diferentes tipos de tablas (cuadro resumen)


Acceso indexado Acceso mediante clave Valores de la clave Acceso preferible Tablas estndar S S NONUNIQUE Indexado Tablas sorted S S UNIQUE o NONUNIQUE Mediante clave Tablas hashed No S UNIQUE Slo mediante clave

2.6.- Tablas genricas


El tipo genrico ANY TABLE significa que un field-symbol o el parmetro de la interfaz de un procedimiento puede ser una tabla interna de cualquier tipo. Adems, los nicos modos de acceso que pueden ser programados son aquellos que se permiten para toda clase de tablas. Concretamente, el acceso indexado no es un caso, toda vez que no es posible realizarlo con tablas hashed. De todos modos, el acceso indexado se puede programar para field-symbols y parmetros de interfaz del tipo genrico TABLE INDEX, porque el tipo actual slo puede ser una tabla con administracin indexada. Tambin podemos hacer uso de las tablas genricas en la sentencia TYPES para crear tipos de tabla genricos autodefinidos, como por ejemplo:
TYPES itab TYPE INDEX TABLE OF type.

O
TYPES itab TYPE ANY TABLE OF type WITH KEY key.

3.- Tipo de lnea


El tipo de lnea de una tabla interna es cualquier tipo de dato global o local de la jerarqua tipo ABAP que est determinada por la clusula TYPE o LIKE. El tipo de lnea de un clsica tabla en ABAP es de estructura plana, y una aplicacin comn para esto es una referencia a la estructura de una tabla de la base de datos. De todos modos, es digno de mencin el papel clave que juegan los arrays de tipos elementales o variables de referencia. Finalmente, hemos de mencionar que los tipos de lnea que contienen en s mismos ms tablas internas son ideales para el manejo de objetos complejos. Un ejemplo de esto ltimo es la estructura cxtab_control, que necesitamos para la gestin de table controls en la impresin de pantalla.

4.- Claves
Una clave tiene por objeto el identificar las columnas de una tabla. Hay dos clases de clave para las tablas internas: las estndar y las definidas por el usuario. Podemos especificar si la clave es UNIQUE o NON-UNIQUE. Caso de que se defina la tabla interna con una clave UNIQUE, dicha tabla no podr contener entradas duplicadas. En sntesis, el que tenga un tipo de clave u otro depende slo del mtodo de acceso. Si una lnea tiene un tipo de lnea estructurado, su clave por defecto consite en todas sus columnas no numricas que no contienen referencias externas ni son tablas internas. 3

Tablas internas

Sin embargo, si una tabla tiene un tipo de lnea elemental, la clave por defecto es la lnea entera. Y finalmente, si el tipo de lnea de la tabla interna es, precisamente, otra tabla interna, la clave por defecto se queda vaca. Por otro lado, las tablas internas con claves definidas por el usuario reciben el nombre de tablas clave. Cuando definimos la clave, hemos de tener cuidado ya que el orden de los campos de la misma tiene importancia. Debemos tener esto presente si, por ejemplo, intentamos ordenar la tabla de acuerdo con la clave.

5.- Definicin de tablas internas


Por definicin, una tabla interna bien puede ser un tipo de dato o un objeto de dato, por lo que la implementacin en ABAP bien podra ser de esta forma:
DATA: BEGIN OF <itab> OCCURS <n>, {<f1>,...,<fn> | INCLUDE STRUCTURE <str>}, END OF <itab>.

O bien de estas otras:


1. TYPES itabtype {TYPE tabkind OF linetype LIKE tabkind OF lineobj} [WITH [UNIQUE NON-UNIQUE] keydef] [INITIAL SIZE n]. 2. TYPES itabtype TYPE RANGE OF type. TYPES itabtype LIKE RANGE OF f. 3. TYPES itabtype {TYPE linetype LIKE lineobj} OCCURS n.

Dependiendo de si la definimos como un objeto de dato o un tipo de dato, respectivamente. En la definicin de la tabla interna, hemos de tener en cuenta que adems se establece una lnea de cabecera o rea de trabajo.

5.1.- Definicin como objeto de datos 5.1.1.- Sentencia OCCURS


Para empezar, hemos de considerar que una tabla interna es, en sntesis, una estructura de datos dinmica. Sus requerimientos de memoria estn constituidos por bloques. La localizacin inicial de memoria (desde ahora la llamaremos rea OCCURS), se puede controlar mediante la clusula OCCURS n o INITIAL SIZE n al final de la definicin de la tabla interna dentro del cdigo de nuestro programa. Una vez que el rea occurs se ha llenado, el siguiente bloque que se crea es dos veces ms grande que el rea recin agotada (con tal de que no sea mayor de 8 Kb). Todos los dems bloques que se crean despus tienen un tamao constante de 12 Kb. No obstante todo lo dicho, tambin tenemos la posibilidad de dejar que sea el propio sistema el que determine el tamao del rea occurs, haciendo n = 0 (como en el ejemplo que veamos en la introduccin). En este caso, el sistema reserva una pequea porcin de memoria tras la primera sentencia insert o append. Ms concretamente, el parmetro n se localiza en un valor comprendido entre 16 y 100 (dependiendo ya del tamao de la lnea). Slo tiene sentido especificar un valor concreto de n mayor que cero en el caso de que sepamos con exactitud el nmero de entradas que va a tener nuestra tabla interna. 4

Tablas internas

En general y para terminar, consideremos que un OCCURS muy grande supone un gran gasto de recursos del sistema, y que otro muy pequeo implica un proceso muy lento, habida cuenta de que necesita de paginacin.

5.1.2.- Estructura de la tabla interna


La forma de la tabla interna se puede definir de dos formas posibles: bien describiendo uno por uno los campos de que va a estar compuesta, o bien pasndole una estructura anloga a otra ya existente previamente en nuestro diccionario de datos: Le definimos los campos uno a uno:
{<f1>,...,<fn>}

O referenciamos una estructura ya existente:


INCLUDE STRUCTURE <str>

5.2.- Definicin como tipo de datos 5.2.1.- Tipo 1


TYPES itabtype {TYPE tabkind OF linetype LIKE tabkind OF lineobj} [WITH [UNIQUE NON-UNIQUE] keydef] [INITIAL SIZE n].

Define el tipo itabtype para una tabla interna sin lnea de cabecera en un programa con un tipo de tabla tabkind y un tipo de lnea linetype (siempre que usemos una referencia TYPE) o el tipo lineobj del objeto referido (si usamos la sentencia LIKE). Las tablas internas sin lnea de cabecera consisten en un nmero de lneas de tabla, que tienen un estructura definida por el tipo de lnea. Tambin podramos definir una clave de tabla. Si no lo hacemos, el sistema crea un tipo de tabla genrica con cualquier clave. Podemos usar tipos genricos para especificar el tipo de parmetros de subrutina genricos. Las clusulas UNIQUE y NON-UNIQUE nos permiten especificar si una tabla de tipo itabtype puede contener dos o ms registros con la misma clave o no. Ms concretamente: 5.2.1.1.- Tablas estndar: La clave es siempre NON_UNIQUE por defecto. No podemos usar la clusula UNIQUE con este tipo de tablas. 5.2.1.2.- Tablas sorted: No hay opciones por defecto para estas tablas. Si no especificamos las clusulas UNIQUE o NON-UNIQUE, el sistema crea un tipo de tabla genrica sin ningn atributo nico en particular. Podemos usar tipos genricos para especificar los tipos de parmetros de subrutina genricos. 5.2.1.3.- Tablas hashed: Al igual que en el caso de las Sorted, tampoco hay opciones por defecto para este tipo de tablas. De todos modos, hemos de definir una clave UNIQUE. La clusula NON-UNIQUE no est permitida. La clusula opcional INITIAL SIZE sirve para especificar cunta memoria deseamos reservar para nuestra tabla al crearla. A continuacin vemos unos cuantos ejemplos de implementacin de cuanto llevamos explicado hasta ahora: 5

Tablas internas

Las siguientes definiciones de tipo implementan tablas usando el tipo de lnea STRUC y la clave NAME:
TYPES: BEGIN OF struc, name(10) TYPE c, age TYPE i, END OF struc. TYPES: tab1 TYPE STANDARD TABLE OF struc WITH DEFAULT KEY, tab2 TYPE SORTED TABLE OF struc WITH NON-UNIQUE KEY name, tab3 TYPE HASHED TABLE OF struc WITH UNIQUE KEY name.

A diferencia de los tipos especificados arriba, los que veremos a continuacin son genricos. Esto significa que podemos usarlos para especificar el tipo de un parmetro de subrutina genrico, pero no para crear una tabla objeto usando la clusula DATA. La nica excepcin a esto es que el sistema nos permite usar un tipo de tabla estndar genrico en una clusula DATA la descripcin del tipo es completada automticamente por el sistema de acuerdo con las reglas descritas debajo de la lnea DATA.
TYPES: gen_tab1 TYPE STANDARD TABLE OF struc, gen_tab2 TYPE SORTED TABLE OF struc WITH KEY name gen_tab3 TYPE HASHED TABLE OF struc.

El siguiente ejemplo muestra la definicin de una tabla sorted usando una referencia LIKE a la estructura del diccionario de datos SFLIGHT:
TYPES: fltab LIKE SORTED TABLE OF sflight WITH NON-UNIQUE KEY carrid connid fldate.

5.2.2.- Tipo 2
TYPES itabtype TYPE RANGE OF type. TYPES itabtype LIKE RANGE OF f.

A todos los efectos crea un tipo de tabla stndar. El tipo de lnea es una estructura, que se configura del siguiente modo:
SIGN(1) TYPE C OPTION(2) TYPE C LOW TYPE type or LIKE f HIGH TYPE type or LIKE f

5.2.3.- Tipo 3
TYPES itabtype {TYPE linetype LIKE lineobj} OCCURS n.

Define el tipo itabtype como el tipo para una tabla estndar sin lnea de cabecera. La clave es la que viene por defecto para las tablas internas. Este tipo tiene el mismo efecto que la siguiente definicin:
TYPES itabtype {TYPE STANDARD TABLE OF linetype LIKE STANDARD TABLE OF lineobj} WITH DEFAULT KEY INITIAL SIZE n.

Nota: El nombre de un tipo puede tener hasta 30 caracteres, y slo puede construirse con letras, cifras y el carcter "_". No est permitido que conste slo de cifras, y los signos especiales como 6

Tablas internas

la diresis tampoco deben usarse. Existen, adems de stos, otros caracteres especiales para objetivos internos que no deberan usarse en los programas de aplicaciones. SPACE es un nombre reservado y tampoco puede usarse. Y en una sentencia no debera utilizarse ningn campo cuyo nombre sea idntico al de uno de los parmetros adicionales de la palabra clave introductoria (Por ejemplo: PERFORM SUB USING CHANGING.). Recomendaciones para nombrar un tipo: 1. Utilicar siempre como primer carcter una letra. 2. El carcter de subrayado resulta til para estructurar nombres que van juntos (z.B. NEW_PRODUCT).

6.- Trabajando con tablas internas


Cuando trabajamos con tablas internas podemos distinguir entre el acceso a lneas individuales de la misma o el acceso a toda la tabla. Para empezar, comenzaremos con el tratamiento de acceso a lneas individuales. En este contexto, podemos distinguir, as mismo, entre acceso mediante clave y acceso indexado. En este apartado slo se pretende presentar los aspectos ms importantes de ambos, sin entrar en demasiados detalles; no obstante, y si nos interesa, siempre podemos encontrar mucha ms informacin en la documentacin on line que SAP nos ofrece.

6.1.- Acceso indexado


Como su propio nombre indica, este tipo de acceso direcciona lneas mediante un ndice interno y slo es posible para tablas estndar y sorted. Tras ser accedida la tabla, la variable de entorno sy-tabix contiene siempre el valor del ndice de la lnea accedida. Aunque la indexada, por lo general, resulta ser la forma ms rpida de acceder a la lnea de una tabla interna, resulta que desde que hay una referencia interna directa, tambin puede resultar que no sea la ms ptima, sobre todo cuando trabajamos con datos de una tabla de la base de datos del diccionario. Cuando trabajamos en esta forma de acceso, el sistema debe saber en todo momento la asignacin habida entre el ndice y el contenido de la lnea de la tabla interna, si bien con el acceso mediante clave primaria el contenido de la lnea interna es evaluado previamente. Debido a ello, nos encontramos con que el acceso mediante clave parece ser ms recomendable para la mayora de las aplicaciones que manejan datos de elementos del diccionario ABAP.

6.2.- Acceso mediante clave primaria


En el acceso mediante clave a tablas estndar, el sistema realiza una bsqueda lineal mediante el valor de la clave. El tiempo medio de bsqueda es directamente proporcional al nmero de lneas de la tabla interna. En el mismo acceso pero a tablas sorted, el entorno de ejecucin del programa realiza una bsqueda binaria para el valor clave. El tiempo medio de bsqueda es directamente proporcional al log2 del nmero de lneas. Y finalmente, con el mismo acceso pero a tablas hashed, el sistema calcula la posicin de la lnea mediante el valor de la clave aplicando una funcin hash. En este caso, el tiempo de bsqueda es independiente del nmero de lneas y se mantiene siempre constante. En el siguiente grfico podemos observar la media de tiempos de acceso para el tipo de clave primaria. En abscisas tenemos el nmero de lneas, mientras que en ordenadas el tiempo de acceso en s. Llama la atencin cmo sube ste en las tablas estndar conforme tambin lo hace el nmero de lneas a tratar.

Tablas internas

540 525 510 495 480 465 450 435 420 405 390 375 360 345 330 315 300 285 270 255 240 225 210 195 180 165 150 135 120 105 90 75 60 45 30 15 0

Tabla estndar Tabla sorted Tabla hashed

10

100

1000

10000

Tipo tabla\No.lneas Tabla estndar Tabla sorted Tabla hashed

10
20 s 18 s 17 s

100
64 s 21 s 17 s

1000
530 s 28 s 17 s

10000
5300 s 31 s 17 s

6.3.- Conclusin
As pues, dependiendo del propsito de la tabla interna dentro de nuestro programa ABAP (nmero de lneas, frecuencia de acceso, etc.) deberamos siempre usar el tipo de tabla adecuado. Por ejemplo, para tablas pequeas con hasta cien lneas, a las que se accede muy espordicamente mediante clave primaria, la implementacin del tipo estndar parece la ms adecuada. Sin embargo, tablas grandes sin entradas duplicadas a las que queramos acceder slo mediante clave primaria, bien podran estar implementadas como tablas hashed. Si se requiere que la tabla permanezca ordenada durante todo el tiempo de ejecucin, se recomienda el uso de tablas sorted2.

7.- Operaciones con tablas internas 7.1.- Sentencia INSERT


1. INSERT [wa INTO INITIAL LINE INTO] itab [INDEX idx]. 2. INSERT [wa INTO INITIAL LINE INTO] TABLE itab. 3. INSERT LINES OF itab1 [FROM idx1] [TO idx2] INTO itab2 [INDEX idx3]. 4. INSERT LINES OF itab1 [FROM idx1] [TO idx2] INTO TABLE itab2.

Si ordenamos una tabla estndar con el comando SORT y hacemos una bsqueda binaria con la clusula BINARY SEARCH en la sentencia READ TABLE, estaremos obteniendo los mismos resultados en tiempo de ejecucin que para las tablas sorted.

Tablas internas

7.1.1.- INSERT [wa INTO INITIAL LINE INTO] itab [INDEX idx].
Esta sentencia inserta un nueva lnea en la tabla interna usando una especificacin implcita o explcita de ndice. Esta variante de la sentencia insert slo podemos usarla con tablas indexadas (estndar o sorted). Si usamos la clusula wa INTO el contenido del work area wa es insertado como una nueva lnea. Si los respectivos tipos de wa y de la tabla interna fuesen incompatibles, el contenido del primero se transfieren de acuerdo con la lgica de proceso de la sentencia MOVE. Si usamos la clusula INITIAL LINE INTO, insertaremos una lnea en la tabla, que contendr valores apropiados de acuerdo con los tipos de que conste dicha tabla. Si no especificamos nada antes de itab, la nueva lnea se toma de la lnea de cabecera de la tabla interna. Por otro lado, usamos INDEX idx para especificar el ndice de la tabla antes del que la nueva lnea va a ser insertada. Si estamos insertando lneas en una tabla indexada usando un LOOP, podemos omitir la especificacin del ndice, ya que la lnea a insertar se introducir antes de la lnea activa en ese momento de la sentencia LOOP; es lo que se llama especificacin indexada implcita). Hemos de tener en cuenta, as mismo, que la insercin de lneas en una tabla dentro de una sentencia LOOP slo tiene efecto en la siguiente pasada de la esta instruccin. Si la tabla en la que estamos introduciendo lneas es del tipo SORTED, sta ha de estar correctamente ordenada despus de terminar de insertar lneas, de lo contrario se producir un error. El cdigo de retorno devuelve los siguientes valores, segn el caso: o SY-SUBRC = 0 La lnea se insert con xito. o SY-SUBRC = 4 El ndice especificado es demasiado grande. La lnea no se insert. Ahora vamos a ver el siguiente ejemplo en el que insertamos valores dentro de una tabla de nmeros enteros:
DATA: VALUE TYPE I, ITAB TYPE I OCCURS 100 WITH HEADER LINE. ITAB = 5. VALUE = 36. INSERT ITAB INDEX 1. INSERT VALUE INTO ITAB INDEX 2. INSERT INITIAL LINE INTO ITAB INDEX 2.

7.1.2.- INSERT [wa INTO INITIAL LINE INTO] TABLE itab.


Inserta valores en una tabla interna con una clave, que es tomada, precisamente, del work area. Si indicamos explcitamente dicho work area, hemos de asegurarnos de que es compatible con el tipo de lnea de la tabla donde queremos insertar. A diferencia de la sentencia anterior, sta puede usarse con cualquier tipo de tabla. Si la tabla donde pretendemos insetar tiene la clusula UNIQUE KEY, el sistema ignora cualquier entrada duplicada. La forma en la que el sistema inserta nuevas entradas en la tabla depende del tipo que sea sta: Tablas estndar: la nueva entrada es aadida al final de la tabla. La insercin genrica es similar a usar la sentencia APPEND. Tablas sorted: la nueva entrada es colocada en el lugar apropiado, que es determinado por la clave de la tabla. Como se ha dicho con 9

Tablas internas

anterioridad, el valor de la clave es tomado directamente del wa o de la lnea de cabecera de la tabla. Si la clave es NON-UNIQUE, la entrada es colocada la primera en la lista de entradas duplicadas. El punto de insercin se determina internamente usando una bsqueda binaria. Tablas hashed: la nueva entrada es colocada en la administracin hash interna de la tabla de acuerdo con la clave de la misma. Como en el anterior caso, los valores de la clave se toman del wa especificado o de la lnea de cabecera de la tabla. El tiempo de ejecucin requerido permanece constante, debido a que no depende del nmero de entradas de la tabla. La clave ha de ser nica. Los cdigos de retorno devuelven los siguientes valores: o SY-SUBRC = 0 Entrada aadida a la tabla. o SY-SUBRC = 4 La entrada no ha podido ser aadida a la tabla, debido a que duplica una entrada existente y la tabla est difinida como UNIQUE KEY. Como ejemplo, vamos a implementar una tabla sorted, ordenada por nombre y edad:
TYPES: BEGIN OF PERSON, NAME(10) TYPE C, AGE TYPE I, END OF PERSON. DATA: P TYPE PERSON, PTAB TYPE SORTED TABLE OF PERSON WITH UNIQUE KEY NAME AGE. P-NAME P-NAME P-NAME P-NAME = = = = 'Steve'. 'Andy'. 'Steve'. 'Andy'. P-AGE P-AGE P-AGE P-AGE = = = = 20. 20. 17. 20. INSERT INSERT INSERT INSERT P P P P INTO INTO INTO INTO TABLE TABLE TABLE TABLE PTAB. PTAB. PTAB. PTAB.

7.1.3.- INSERT LINES OF itab1 [FROM idx1] [TO idx2]


INTO itab2 [INDEX idx3]

Inserta la tabla interna itab1 o parte de la misma dentro de la tabla interna itab2. Esta sentencia viene a equivaler a insertar lnea por lnea dentro de un bucle LOOP. En el ndice idx3 especificamos la posicin del ndice de la tabla antes de la cual queremos insertar la entrada en itab2. Este parmetro no puede ser del tipo HASHED o ANY TABLE, debido a que estas tablas no tienen definidas operaciones indexadas. Volvemos a repetir que si estamos insertando en un LOOP, podemos omitir idx3. Podemos restringir el nmero de lneas tomadas de la tabla fuente usando FROM idx1 TO idx2. Si omitimos el primero (idx1), la seleccin comienza en la primera lnea de la tabla interna; de manera anloga, si lo que omitimos es idx2, la seleccin terminar en la ltima lnea de la tabla fuente. Esto quiere decir que si omitimos ambos parmetros, ser la totalidad de la tabla fuente la que se copie en la tabla destino. Vamos ahora a ver el siguiente ejemplo consistente en la introduccin de una tabla de nombres en otra:
TYPES NAME(10) TYPE C. DATA: NAME_TAB_1 TYPE STANDARD TABLE OF NAME WITH NON-UNIQUE DEFAULT KEY INITIAL SIZE 5, NAME_TAB_2 TYPE STANDARD TABLE OF NAME WITH NON-UNIQUE DEFAULT KEY INITIAL SIZE 5.

10

Tablas internas

APPEND 'Alice' TO NAME_TAB_1. APPEND 'Martha' TO NAME_TAB_1. APPEND 'Ruth' TO NAME_TAB_1. APPEND 'Harry' TO NAME_TAB_2. APPEND 'Walter' TO NAME_TAB_2. INSERT LINES OF NAME_TAB_1 FROM 2 INTO NAME_TAB_2 INDEX 2.

7.1.4.- INSERT LINES OF itab1 [FROM idx1] [TO idx2]


INTO TABLE itab2.

Insercin genrica de la tabla interna itab1 o parte de la misma dentro de la tabla interna itab2. A diferencia del anterior caso, este tipo de insercin se puede usar con cualquier tipo de tabla origen y destino. La forma en que las lneas se toman de la tabla origen itab1 y son insertadas en la tabla itab2 depende, fundamentalmente, del tipo de tabla que sea itab2. Recomendaciones para la implementacin: o Hemos de evitar en lo posible asignaciones innecesarias en la lnea de cabecera. Cuando podamos, debemos usar sentencias que tengan un wa explcito. Por ejemplo, APPEND wa TO itab es mucho ms simple y rpido que itab = wa. APPEND itab. Podemos hacer anlogas observaciones para las clusulas COLLECT e INSERT. o Cuando aadimos una lnea a un ndice de tabla, el mantenimiento de ste va en detrimento del tiempo de acceso e insercin. Por ejemplo, para la insercin de una lnea dentro de una tabla interna de 100 bytes de tamao y 200 entradas, necesitaremos alrededor de 90 msn (microsegundos estndar) . o A la hora de insertar tablas internas o parte de ellas dentro de otras, la sentencia INSERT LINES OF resulta mucho ms eficiente que ir aadiendo lneas una a una dentro de un bucle LOOP.

7.2.- Sentencia COLLECT


COLLECT <wa> INTO <itab>.

Suma el contenido de la lnea de cabecera en la tabla que estemos tratando. La tabla en cuestin ha de tener un tipo de lnea plano, y todos los campos que no pertenzcan a la clave de la tabla han de ser tipo numrico lgicamente-, para poder sumarlos. El sistema, al insertar la nueva lnea comprueba si existe en la tabla una entrada que se corresponda con la clave primaria; de no haberla, esta sentencia tiene el mismo efecto que la de insertar lneas nuevas. Si ya hay una entrada que coincida con la clave, COLLECT no realiza el APPEND correspondiente, pero no as suma los contenidos de los campos numricos habidos en el work area a los campos de idnticos tipos de la entrada existente. En general, esta sentencia se debera usar slo en el caso de que el usaurio dese realizar sumatorias con los campos de una tabla, debido a que esta instruccin es manifiestamente ms lenta que READ, INSERT o MODIFY. Las lneas se suman a las tablas internas tal y como se explica a continuacin: o Tablas estndar: Si la sentencia COLLECT es la primera en empezar a rellenar la tabla, el sistema crea una administracin hash temporal para identificar las entradas existentes en la tabla. Dicha administracin hash permanece activa hasta que otra sentencia cambia los contenidos de los campos clave o la secuencia de las 11

Tablas internas

lneas de la tabla interna. Despus, el sistema encuentra entradas existentes mediante una bsqueda lineal. El tiempo de ejecucin de esta operacin se incrementa linealmente en funcin del nmero de entradas exitentes en la tabla. La variable de sistema SY-TABIX contiene el ndice de la lnea insertada o modificada en la sentencia COLLECT. o Tablas sorted: En este caso, el sistema realiza una bsqueda binaria para localizar las entradas existentes. El tiempo de ejecucin de esta operacin se incrementa logartmicamente con el nmero de lneas existentes. La variable de sistema SY-TABIX contiene el ndice de la lnea insertada o modificada en la sentencia COLLECT. o Tablas hashed: El sistema encuentra las lneas existentes utilizando un algoritmo hash de la tabla interna. Tras la sentencia COLLECT, la variable de sistema SY-TABIX contiene el valor 0, debido a que las tablas hashed no tiene ndice lineal. Veamos el siguiente ejemplo:
DATA: BEGIN OF LINE, COL1(3) TYPE C, COL2(2) TYPE N, COL3 TYPE I, END OF LINE. DATA ITAB LIKE SORTED TABLE OF LINE WITH NON-UNIQUE KEY COL1 COL2. LINE-COL1 = 'abc'. LINE-COL2 = '12'. LINE-COL3 = 3. COLLECT LINE INTO ITAB. WRITE / SY-TABIX. LINE-COL1 = 'def'. LINE-COL2 = '34'. LINE-COL3 = 5. COLLECT LINE INTO ITAB. WRITE / SY-TABIX. LINE-COL1 = 'abc'. LINE-COL2 = '12'. LINE-COL3 = 7. COLLECT LINE INTO ITAB. WRITE / SY-TABIX. LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2, LINE-COL3. ENDLOOP.

Cuya salida sera:


1 2 1 abc 12 10 def 34 5

Este ejemplo rellena una tabla sorted. Las primeras dos sentencias COLLECT funcionancomo sentencias INSERT normales y corrientes. En la tercera sentencia 12

Tablas internas

COLLECT, la primera lnea de ITAB se modifica. Con el siguiente diagrama vemos los tres pasos grficamente:

7.3.- Lectura de tablas internas


Para la lectura de una nica lnea de una tabla interna, hemos de usar la sentencia:
READ TABLE <itab> <key> <result>.

Para que ducha sentencua sea vlida para cualquier tipo de tabla, debemos especificar la entrada usando la calve y no el ndice. La parte <result> puede especificar alguna opcin ms de procesamiento para la lnea que se va a leer. Si el sistema encuentra una entrada, pone a cero la variable de sistema SY-SUBRC, de lo contrario, la pone a cuatro. Si la tabla que se est tratando es del tipo indexado, SYTABIX contiene el ndice de la lnea leda. Si la tabla tiene la clusula NON-UNIQUE KEY y tiene entradas duplicadas, slo se lee la primera lnea.

7.3.1.- Especificacin de la clave de bsqueda


sta puede ser, bien la clave de la tabla o bien cualquier otra: o Clave de la tabla: Para usar la clave primaria de la tabla, hemos de usar la siguiente sentencia:
READ TABLE <itab> FROM <wa> <result>.

o sta otra:
READ TABLE <itab> WITH TABLE KEY <k1> = <f 1> ... <k n> = <f n> <result>.

En el primer caso, <wa> debe ser un work area compatible con el tipo de linea de <itab>. Los valores de los campos de la clave se toman de los componentes correspondientes del work area. En el segundo caso, debemos especificar los valores de cada campo de la clave explcitamente. Si no sabemos alguno de los nombres de los campos clave hasta el tiempo de ejecucin, podemos especificarlo como el contenido de un campo <n i > utilizando la forma (<n i >) = <f i >. Si el tipo 13

Tablas internas

de datos de <f i > no es compatible con los campos de la clave, el sistema los convierte automticamente. El sistema realiza la bsqueda de la siguiente forma: Tablas estndar Bsqueda lineal, donde el tiempo de ejecucin es directamente proporcional al nmero de entradas de la tabla. Tablas sorted Bsqueda binaria, donde el tiempo de ejecucin est en proporcin logartmica al nmero de entradas de la tabla. Tablas hashed La entrada se encuentra usando un algoritmo hash de la tabla interna. Como ya se ha dicho anteriormente, el tiempo de ejecucin en estos casos es indpendiente del nmero de entradas. o Uso de otra clave: Para hacer uso de una clave que no sea la de la tabla interna, hemos de introducir el parmetro <key> como se explica:
READ TABLE <itab> WITH KEY = <f> <result>.

o de esta otra forma:


READ TABLE <itab> WITH KEY <k1> = <f1> ... <k n> = <f n> <result>.

En el primer caso, la lnea de la tabla interna en su totalidad se usa como calve de bsqueda. Los contenidos de la lnea de la tabla entera se comparan con los contenidos del campo <f>. Si <f> no es compatible con el tipo de lnea de la tabla, el valor se convierte al tipo de lnea de la tabla. La bsqueda por clave nos permite encontrar entradas en tablas internas que no tienen un tipo de lnea estructurado, es decir, tienen un tipo de lnea que consiste en un nico campo o en un tipo de tabla interna. En el segundo caso, la clave de bsqueda puede consistir en cualquier de los campos de la tabla <k 1 >...<k n >. Si no sabemos alguno de los nombres de los campos clave hasta el tiempo de ejecucin, podemos especificarlo como el contenido de un campo <n i > utilizando la forma (<n i >) = <f i >. Si el tipo de datos de <f i > no es compatible con los campos de la clave, el sistema los convierte automticamente. Podemos restringir la bsqueda a campos parciales especificando el desplazamiento y la longitud. La bsqueda es lineal para todo tipo de tablas. El tiempo de ejecucin, en este caso, y siendo la bsqueda lineal, va en proporcin directa al nmero de entradas de la tabla.

7.3.2.- Especificacin de la opcin de procesamiento


Podemos especificar una opcin que contenga cuanto queremos que el sistema haga con la entrada recin encontrada. Para ello exiten dos maneras: o Mediante el work area: Podemos escribir la entrada de tabla leda dentro de un work area con la clusula <result>:
READ TABLE <itab> <key> INTO <wa> [COMPARING <f1> <f 2> ... |ALL FIELDS] [TRANSPORTING <f1> <f 2> ... |ALL FIELDS |NO FIELDS].

14

Tablas internas

Si no usamos los parmetros COMPARING o TRANSPORTING, los contenidos de la lnea de la tabla debe ser convertible al tipo de dato del work area <wa>. Si especificamos dichos parmetros, tanto el tipo de lnea como el wa han de ser compatibles. Siempre deberamos usar un work area que sea compatible con el tipo del lnea pertinente de la tabla interna. Si usamos el parmetro COMPARING, los campos de la tabla especificados <fi> del tipo de lnea estructurado son comparados con los campos correspondientes del work area antes de ser transportados. Si hacemos uso de la opcin ALL FIELDS, el sistema compara todos los componentes. Si el sistema encuentra una entrada con la clave especificada <key> y si los contenidos de los campos comparados son los mismos, SYSUBRC pasa a contener el valor 0. Si el contenido de los campos comparados no son los mismos, SY-SUBRC devuelve el valor 2. Y por ltimo, si el sistema no encuentra ninguna entrada, esta variable de sistema contiene el valor 4. Si el sistema encuantra una entrada, la copia en el work area sin importar el resultado de la comparacin. Si usamos la opcin TRANSPORTING, podemos especificar los campos de la tabla del tipo de lnea estructurado que queremos transportar al work area. Si definimos ALL FIELDS sin TRANSPORTING, se transportarn todos los contenidos de todos los campos. Si escribimos NO FIELDS, no se transportar ningn campo. Por ltimo, debemos sealar que especificar el work area con TRANSPORTING NO FIELDS es innecesario, y no debera usarse. En ambos casos (COMPARING y TRANSPORTING), podemos definir un campo <f i > dinmicamente como el contenido de un campo <n i > en la forma (<n i >). Si <n i > est vaco cuando se ejecuta la sentencia, ste se ignora. Podemos restringir la bsqueda a campos parciales especificando el desplazamiento y la longitud. o Mediante un Field-Symbol: Podemos asignar la entrada de tabla leda a un filed-symbol definiendo <result> de la siguiente manera:
READ TABLE <itab> <key> ASSIGNING <FS>.

Despus de la sentencia READ, el field-symbol apunta a la lnea de la tabla. Si ste es de tipo estructurado, deberamos declarar el mismo tipo para el field-symbol al declararlo. Esto nos permite direccionar los componentes del field-symbol. Si no especificamos el tipo estticamente, debemos usar ms field-symbols y la tcnica de asignacin de componentes de estructuras para direccionarlas. Veamos, ahora, los siguientes ejemplos:
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO.

15

Tablas internas
LINE-COL1 = 2. LINE-COL2 = 3. READ TABLE ITAB FROM LINE INTO LINE COMPARING COL2. WRITE: 'SY-SUBRC =', SY-SUBRC. SKIP. WRITE: / LINE-COL1, LINE-COL2.

La salida que genera el programa es: SY-SUBRC = 2 2 4

El programa rellena una tabla hashed con una lista de nmeros cuadrados.El work area LINE, que es compatible con el tipo de lnea, se rellena con los nmeros 2 y 3. La sentencia READ lee la lnea de la tabla en la que el campo clave COL1 tiene el mismo valor que en el work area y lo copia en ste. SY-SUBRC toma el valor 2,
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE SORTED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. CLEAR LINE. READ TABLE ITAB WITH TABLE KEY COL1 = 3 INTO LINE TRANSPORTING COL2. WRITE: 'SY-SUBRC =', SY-SUBRC, / 'SY-TABIX =', SY-TABIX. SKIP. WRITE: / LINE-COL1, LINE-COL2.

Y su salida es:
SY-SUBRC = SY-TABIX = 0 0 3 9

El programa rellena una tabla ordenada con una lista de nmeros cuadrados tambin. La sentencia READ lee la lnea de la tabla en la que el campo clave COL1 tiene el mismo valor que en el work area y lo copia en ste. Slo el contenido de COL2 es copiado al work area LINE. SY-SUBRC se pone a cero, y SY-TABIX en 3, porque ITAB es un ndice de la tabla.

16

Tablas internas

DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE SORTED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. READ TABLE ITAB WITH KEY COL2 = 16 TRANSPORTING NO FIELDS. WRITE: 'SY-SUBRC =', SY-SUBRC, / 'SY-TABIX =', SY-TABIX.

Y la salida es:
SY-SUBRC = SY-TABIX = 0 4

El programa rellena una tabla sorted con una lista de nmeros cuadrados. La sentencia READ lee la lnea de la tabla en la que el campo clave tiene el valor 16. No usa la clave de la tabla. No se copia ningn campo al work area ni se asigna a ningn field-symbol. En lugar de eso, son las variables de sistema SY-SUBRC (con valor 0, ya que se encontr la lnea) y SY-TABIX (con valor 4) los nicos que toman algn valor.
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1. FIELD-SYMBOLS <FS> LIKE LINE OF ITAB. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. READ TABLE ITAB WITH TABLE KEY COL1 = 2 ASSIGNING <FS>. <FS>-COL2 = 100. LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2. ENDLOOP.

Y la salida de este programa es:


1 2 1 100

17

Tablas internas
3 4 9 16

El programa rellena una tabla hashed con una lista de nmeros cuadrados, como en los casos anteriores. La sentencia READ lee la lnea de la tabla en la que el campo clave COL1 tiene el valor 2, y lo asigna al field-symbol <fs>. El programa, entonces, asigna el valor 100 al componente COL2 de <fs>. Esto tambin cambia el campo de la tabla correspondiente.

7.4.- Modificacin de lneas


Para cambiar una nica lnea de una tabla interna, debemos usar la sentencia MODIFY. Tambin podemos hacer uso de la clave de la tabla para encontrar y cambiar una lnea usando su clave, o encontrar y cambiar un conjunto de lneas que satisfagan cierta condicin. Si la tabla est definida con la clusula NON-UNIQUE KEY y hay entradas duplicadas, slo se modificar la primera entrada.

7.4.1.- Cambio de una lnea mediante la clave de la tabla


Para modificar una lnea, hemos de usar la siguiente sentencia:
MODIFY TABLE <itab> FROM <wa> [TRANSPORTING <f1> <f 2> ...].

El work area <wa>, que debe ser compatible con el tipo de lnea de la tabla interna, juega un doble papel en esta sentencia. No slo se utiliza para cambiar la lnea que se desea cambiar, sino que tambin contine los nuevos valores. El sistema busca en la tabla interna la lnea cuya clave de tabla coincida con los campos clave de <wa>. Las bsquedas en los diferentes tipos de tabla son de la msma ndole que las explicadas hasta ahora; a saber: bsqueda lineal, binaria y algoritmo hash para tablas estndar, sorted y hashed, respectivamente, con las caractersticas anteriormente descritas. De igual forma, las variables de sistema cambian de valor de manera idntica a la descrita hasta ahora.

7.4.2.- Cambiar varias lneas mediante una condicin


Para cambiar una o ms lneas mediante una condicin, hemos de utilizar la siguiente sentencia:
MODIFY <itab> FROM <wa> TRANSPORTING <f1> <f 2> ... WHERE <cond>.

Esto procesa todas las lneas que satisfagan la condicin lgica <cond>. sta puede consistir en ms de una comparacin. En cada una de ellas, el primer operando debe ser un componente de la estructura de la lnea. Si las lneas de la tabla no estn estructuradas, el primer operando tambin puede ser la expresin TABLE LINE. La comparacin entonces se aplica a la lnea entera. El work area <wa>, que ha de ser compatible con el tipo de lnea de la tabla interna, contiene ahora los nuevos valores, que se asignarn a la lnea pertinente de la tabla mediante el parmetro TRANSPORTING. A diferencia de la sentencia MODIFY de arriba, en este caso TRANSPORTING no es opcional. Adems, slo podemos modificar los campos clave de la tabla interna si sta es estndar. Con tal de que una sola lnea sea cambiada, SY-SUBRC devuelve el valor 0, en caso contrario, 4. Veamos los siguientes ejemplos: 18

Tablas internas

DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. LINE-COL1 = 2. LINE-COL2 = 100. MODIFY TABLE ITAB FROM LINE. LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2. ENDLOOP.

Que genera la siguiente salida:


1 2 3 4 1 100 9 16

Como podemos comprobar, el programa rellena una tabla hashed, y modifica el valor pertinente en la sentencia MODIFY (en este caso el 2). Aqu tenemos otro programa:
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. LINE-COL2 = 100. MODIFY ITAB FROM LINE TRANSPORTING COL2 WHERE ( COL2 > 1 ) AND ( COL1 < 4 ). LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2. ENDLOOP.

Cuya salida es:

19

Tablas internas 1 2 3 4 1 100 100 16

Este ltimo rellena la tabla hashed, en primer trmino, para despus modificarla segn la condicin ( COL2 > 1 ) AND ( COL1 < 4 ).

7.5.- Borrado de lneas


Deberemos usar la sentencia DELETE para borrar una lnea de una tabla interna. Tambin podemos hacer uso de la clave de la tabla para encontrar y borrar la lnea que nos interese, o un conjunto de ellas que satisfagan una condicin, o un conjunto de entradas duplicadas. Si la tabla est definida con la clusula NON-UNIQUE KEY y hay entradas duplicadas, slo se borrar la primera.

7.5.1.- Borrar una lnea mediante la clave de tabla


Debemos usar la siguiente sentencia:
DELETE TABLE <itab> FROM <wa>. O: DELETE TABLE <itab> WITH TABLE KEY <k1> = <f 1> ... <k n> = <f n>.

En el primer caso, <wa> debe ser compatible con el tipo de lnea de <itab>. Los calores de los campos de la clave se toman de los componentes correspondientes del work area. En el segundo caso, hemos de sealar los valores de cada campo explcitamente. Si no sabemos alguno de los nombres de los campos clave hasta el tiempo de ejecucin, podemos especificarlo como el contenido de un campo <n i > utilizando la forma (<n i >) = <f i >. Si los tipos de datos de <fi> no son compatibles con los campos de la clave, el sistema los convierte automticamente. La bsqueda en los diferentes tipos de tablas se realizan como ya se ha comentado en apartados anteriores y los valores de las variables de sistema se establecen conforme a lo anteriormente descrito, tambin.

7.5.2.- Borrar varias lneas mediante una condicin


Para borrar varias lneas de una tabla bastar usar la siguiente sentencia:
DELETE <itab> WHERE <cond>.

<cond> puede ser, bien una sola condicin, o bien varias.

7.5.3.- Borrar entradas duplicadas adyacentes


Usaremos la siguiente sentencia:
DELETE ADJACENT DUPLICATE FROM <itab> [COMPARING <f1> <f 2> ... |ALL FIELDS].

Las entradas estn duplicadas si satisfacen uno de los siguientes criterios de comparacin: 20

Tablas internas

o Sin el parmetro COMPARING, los contenidos de los campos de la clave de la tabla deben ser idnticos en ambas lneas. o Si usamos el parmetro COMPARING <f1> <f 2> ... los contenidos de los campos especificados <f 1 > <f 2 > ... deben ser idnticos, tambin, para ambas lneas. o Y si usamos el parmetro COMPARING ALL FIELDS los contenidos de todos los campos de ambas lneas deben ser iguales. Podemos usar esta sentencia para borrar todas las entradas duplicadas de la tabla interna si sta se encuentra ordenada por el criterio de comparacin especificado. La variable de sistema SY-SUBRC pasa a tener el valor 0 con tal de que una sola lnea haya sido borrada. Veamos ahora algunos ejemplos:
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. LINE-COL1 = 1. DELETE TABLE ITAB: FROM LINE, WITH TABLE KEY COL1 = 3. LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2. ENDLOOP.

Que genera esta salida: 2 4 4 16

El programa, primero, rellena una tabla interna con una lista de nmero cuadrados. Posteriormente, la sentencia DELETE borra las lneas de la tabla interna que contienen en COL1 el valor 1 o 3.
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1. DO 4 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. DELETE ITAB WHERE ( COL2 > 1 ) AND ( COL1 < 4 ).

21

Tablas internas
LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2. ENDLOOP.

Cuya salida es:


1 4 1 16

En este otro, vemos otra sentencia DELETE con otra condicin lgica.
DATA OFF TYPE I. DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE C, END OF LINE. DATA ITAB LIKE STANDARD TABLE OF LINE WITH NON-UNIQUE KEY COL2. LINE-COL1 LINE-COL1 LINE-COL1 LINE-COL1 LINE-COL1 LINE-COL1 LINE-COL1 = = = = = = = 1. 1. 1. 2. 3. 4. 5. LINE-COL2 LINE-COL2 LINE-COL2 LINE-COL2 LINE-COL2 LINE-COL2 LINE-COL2 = = = = = = = 'A'. 'A'. 'B'. 'B'. 'B'. 'B'. 'A'. APPEND APPEND APPEND APPEND APPEND APPEND APPEND LINE LINE LINE LINE LINE LINE LINE TO TO TO TO TO TO TO ITAB. ITAB. ITAB. ITAB. ITAB. ITAB. ITAB.

OFF = 0. PERFORM LIST. DELETE ADJACENT DUPLICATES FROM ITAB COMPARING ALL FIELDS. OFF = 14. PERFORM LIST. DELETE ADJACENT DUPLICATES FROM ITAB COMPARING COL1. OFF = 28. PERFORM LIST. DELETE ADJACENT DUPLICATES FROM ITAB. OFF = 42. PERFORM LIST. FORM LIST. SKIP TO LINE 3. LOOP AT ITAB INTO LINE. WRITE: AT /OFF LINE-COL1, LINE-COL2. ENDLOOP. ENDFORM.

Que genera esta otra salida:


1 A 1 A 1 A 1 B 1 A 2 B 1 A 2 B

1 B 2 B 3 B 5 A

22

Tablas internas 2 B 3 B 4 B 5 A 5 A 3 B 4 B 4 B 5 A

Este ltimo ejemplo crea y rellena una tabla estndar. La primera sentencia DELETE borra la segunda lnea de ITAB ya que tiene los mismos contenidos que la primera. La segunda sentencia DELETE borra la segunda lnea de la tabla resultante de la primera oparacin porque los contenidos del campo COL1 son idnticos que los de la primera lnea. El tercer DELETE borra la tercera y cuarta lnea porque los contenidos del campo clave por defecto COL2 son los mismos que la segunda lnea. Aunque los contenidos de las claves por defecto son los mismos para las lneas primera y quinta, sta ltima no se borra al no ser adyacente a la primera.

7.6.- Prodcesamiento de tablas en sentencias LOOP


Podemos usar la sentencia LOOP para el procesamiento y recorrido de cualquier tabla interna:
LOOP AT <itab> <result> <condition>. <statement block> ENDLOOP.

Esta instruccin lee las lneas de la tabla una a una tal y como se especificara en <result>. Adems, podemos realizar el LOOP para todas las entradas de la tabla, o bien restringir el recorrido slo para parte de ella, especificando una condicin (<condition>). Se permite cierto control del nivel de procesamiento dentro del LOOP. La secuencia en la que las lneas se procesan depende del tipo de tabla: o Tablas estndar y sorted: Las lneas se procesan de acuerdo con un ndice lineal. Dentro del bloque de procesamiento, la variable de sistema SY-TABIX contiene el ndice de la lnea actual de procesamiento. o Tablas hashed: Mientras la tabla no est ordenada, las lneas se procesan en el orden en que han sido aadidas a la tabla. Dentro del bloque de procesamiento, SY-TABIX se mantiene constante a 0. As mismo, podemos anidar bloques LOOP. Cuando abandonamos un buqle LOOP, SYTABIX recupera el valor que tena justo antes de entrar en l. Adems, SY-SUBRC toma el valor 0 con tal de que al menos una entrada de la tabla haya sido procesada. Dentro de un bucle LOOP no se permite realizar operaciones a nivel global de la tabla, sino de lnea a lnea individualmente.

7.6.1.- Definiendo una opcin de procesamiento extra


La opcin de procesamiento especifica cmo se puede disponer de una lnea dentro de la lnea de procesamiento.

7.6.1.1.- Mediante el work area


Para colocar la lnea actual del LOOP en un work area, hemos de definir <result> de la siguiente forma: 23

Tablas internas
LOOP AT <itab> INTO <wa> <condition>.

Los contenidos de las lneas de la tabla han de poder ser convertibles al tipo del wa. En cada pasada del LOOP, una lnea de la tabla se copia en el wa. El final del LOOP no afecta al wa, es decir, los contenidos del wa son los mismos despus de la sentencia ENDLOOP ya que fueron copiados en la ltima pasada del bucle.

7.6.1.2.- Mediante un field-symbol


Para asignar el contenido de la lnea actual del LOOP a un field-symbol, debemos especificar <result> de la siguiente manera:
LOOP AT <itab> ASSIGNING <FS> <conditions>.

En cada pasada del LOOP, el field symbol <fs> apunta a la lnea de la tabla leda. Si el tipo de lnea es estructurado, deberamos especificar el mismo tipo para el field symbol al declararlo. Esto nos permite direccionar los componentes del field symbol. Como en el caso del work area, el final del bucle LOOP no afecta al fieldsymbol, debido a que ste se queda apuntando a la ltima lnea de la tabla tras la ltima pasada del bucle.

7.6.1.3.- Suprimiendo la asignacin de lneas


Si no necesitamos transferir los contenidos de la lnea de la tabla actual a un work area ni a un field-symbol, podemos usar la siguiente sentencia:
LOOP AT <itab> TRANSPORTING NO FIELDS <condition>.

Esta modalidad de LOOP es especialmente til si queremos encontrar el ndice de una tabla interna particular, o el nmero de lneas de una tabla que satisfagan una cierta condicin.

7.6.2.- Especificacin de condiciones


Para evitar el tener que leer la totalidad de las lneas de una tabla interna, podemos especificar una condicin de seleccin de la siguiente manera:
LOOP AT <itab> <result> WHERE <cond>.

Aqu accederemos secuencialmente a las lneas que slo satisfagan ciertas condiciones. Si las lneas de la tabla no son estructuradas, el primer operando de la condicin puede ser TABLE LINE. La comparacin entonces se aplica a toda la lnea.

7.6.3.- Control del nivel de procesamiento


Este control consiste en que podemos dividir secuencias de entradas en grupos basndonos en el contenido de ciertos campos. Las tablas internas estn divididas en grupos de acuerdo con la secuencia de los campos en la lnea estructurada. Dicho de otro modo, nos es posible estructurar el desarrollo del LOOP en funcin de los valores de los campos, segn las siguientes variantes:

24

Tablas internas

<level> FIRST LAST NEW <f> END Of <f>

Meaning Primera lnea de la tabla interna ltima lnea de la tabla interna Comienzo de un grupo de lneas con contenidos idnticos en el campo <f> Final de un grupo de lneas con contenidos idnticos en el campo <f>

El siguiente diagrama ilustra el control de nivel de procesamiento en una tabla ordenada, donde los diferentes contenidos de cada campo se diferencian por el color:

Con la sentencia AT se nos permite gestionar la sentencia LOOP en funcin de esos cambios en los contenidos de los campos que aqu referenciamos mediante un cambio de color. En general, la sentencia AT tiene el siguiente aspecto:
LOOP AT <itab>. AT FIRST. ... ENDAT. AT NEW <f1>. ...... ENDAT. AT NEW <f2 >. ...... ENDAT. ....... <single line processing> ....... AT END OF <f2>. ... ENDAT. AT END OF <f1>. ... ENDAT.

25

Tablas internas
AT LAST. .... ENDAT. ENDLOOP.

Si estamos trabajando con un wa, ste no contiene la lnea actual en el bloque AT ENDAT. Todos los caracteres a la derecha de la actual clave de grupo son rellenados con asteriscos. Todos los dems campos a la derecha de la clave de grupo actual contienen su valor inicial. Dentro de un bloque AT ENDAT, podemos calcular los contenidos de los campos numricos correspondientes al nivel actual mediante la sentencia SUM. Si la tabla contiene otra tabla anidada, no podremos usar la sentencia SUM. Veamos los siuientes ejemplos:
DATA: BEGIN OF LINE, COL1 TYPE C, COL2 TYPE I, COL3 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1 COL2. LINE-COL1 = 'A'. DO 3 TIMES. LINE-COL2 = SY-INDEX. LINE-COL3 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. LINE-COL1 = 'B'. DO 3 TIMES. LINE-COL2 = 2 * SY-INDEX. LINE-COL3 = ( 2 * SY-INDEX ) ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. SORT ITAB. LOOP AT ITAB INTO LINE. WRITE: / LINE-COL1, LINE-COL2, LINE-COL3. AT END OF COL1. SUM. ULINE. WRITE: / LINE-COL1, LINE-COL2, LINE-COL3. SKIP. ENDAT. AT LAST. SUM. ULINE. WRITE: / LINE-COL1, LINE-COL2, LINE-COL3. ENDAT. ENDLOOP.

Que genera la siguiente salida: A 1 1 A 2 4

26

Tablas internas A 3 9 ________________________________ A B B 4 16 B 6 36 ________________________________ B 12 56 6 2 14 4

________________________________ * 18 70

El programa crea una tabla hashed ITAB, la rellena con seis lneas y la ordena. En el bloque LOOP-ENDLOOP, el work area LINE es presentado por pantalla en cada pasada del LOOP. El primer campo de la clave de la tabla, COL1, se usa para el control del nivel de procesamiento. El total para todos los campos numricos siempre se calcula cuando el contenido de COL1 cambia y el sistema se encuentra en la ltima pasada del LOOP.
DATA: BEGIN OF LINE, CARRID TYPE SBOOK-CARRID, CONNID TYPE SBOOK-CONNID, FLDATE TYPE SBOOK-FLDATE, CUSTTYPE TYPE SBOOK-CUSTTYPE, CLASS TYPE SBOOK-CLASS, BOOKID TYPE SBOOK-BOOKID, END OF LINE. DATA ITAB LIKE SORTED TABLE OF LINE WITH UNIQUE KEY TABLE LINE. SELECT CARRID CONNID FLDATE CUSTTYPE CLASS BOOKID FROM SBOOK INTO CORRESPONDING FIELDS OF TABLE ITAB. LOOP AT ITAB INTO LINE. AT FIRST. WRITE / 'List of Bookings'. ULINE. ENDAT. AT NEW CARRID. WRITE: / 'Carrid:', LINE-CARRID. ENDAT. AT NEW CONNID. WRITE: / 'Connid:', LINE-CONNID. ENDAT. AT NEW FLDATE. WRITE: / 'Fldate:', LINE-FLDATE. ENDAT.

27

Tablas internas
AT NEW CUSTTYPE. WRITE: / 'Custtype:', LINE-CUSTTYPE. ENDAT. WRITE: / LINE-BOOKID, LINE-CLASS. AT END OF CLASS. ULINE. ENDAT. ENDLOOP.

En este ejemplo, la tabla sorted interna es rellenada con datos de la tabla de la base de datos SBOOK mediante la sentencia SELECT. La secuencia de las columnas en la tabla interna define la jerarqua del nivel de control. Debido a que la clave de la tabla es la lnea entera, la sequencia de ordenacin y la jerarqua del nivel de control son las mismas. El programa genera la siguiente salida:
List of Bookings Carrid: AA Connid: 0017 Fldate: 1998/11/22 Custtype: B 00063509 C 00063517 C ... ______________________________________________ 00063532 F 00063535 F ... ______________________________________________ Custtype: P 00063653 C 00063654 C ... ______________________________________________ 00063668 F 00063670 F ... ______________________________________________ Fldate: 1998/29/11 Custtype: B 00064120 C 00064121 C ...

Y contina.

7.7.- Inicializar tablas


Como cualquier otro objeto de datos, las tablas internas pueden ser inicializadas con esta sentencia:
CLEAR <itab>.

Este sentencia reestablece una tabla interna al estado en el que se encontraba inmediatamente despues de haber sido declarada. Esto significa que a partir de entonces la 28

Tablas internas

tabnla interna no contiene ninguna lnea. Sin embargo, la memoria ya ocupada por la tabla interna hasta que la reinicializamos con CLEAR permanece localizada y reservada. Si estamos usando tablas internas con lneas de cabecera, hemos de recordar que tanto las tablas como sus lneas de cabecera tienen el mismo nombre. Si lo que queremos es referenciar el cuerpo de la tabla, habremos de invocar el nombre de la misma seguido con un par de corchetes ([ ]):
CLEAR <itab>[].

Para asegurarnos de que la tabla se ha inicializado, podemos usar la sentencia siguiente:


REFRESH <itab>.

sta siempre se aplica al cuerpo de la tabla. As como en la sentencia CLEAR, sta ltima deja reservado el espacio de memoria que tena la tabla. No obstante, si lo que queremos es liberar dicho espacio en memoria, usaremos la siguiente sentencia:
FREE <itab>.

Hemos de recordar que esta sentencia tiene efecto sobre el cuerpo de la tabla y no sobre el work area.
DATA: BEGIN OF LINE, COL1, COL2, END OF LINE. DATA ITAB LIKE TABLE OF LINE. LINE-COL1 = 'A'. LINE-COL2 = 'B'. APPEND LINE TO ITAB. REFRESH ITAB. IF ITAB IS INITIAL. WRITE 'ITAB is empty'. FREE ITAB. ENDIF.

Y la salida del programa es:


ITAB is empty.

En este programa, una tabla interna ITAB se rellena primero, y se inicializa con REFRESH, despus. La sentencia IF utiliza la expresin ITAB IS INITIAL para averiguar si ITAB est vaca o no. De estarlo, la memoria es borrada.

7.8.- Ordenacin de tablas internas


En ABAP podemos ordenar una tabla estndar o hashed, para lo que usaremos la sieguiente sentencia:
SORT <itab> [ASCENDING|DESCENDING] [AS TEXT] [STABLE].

29

Tablas internas

Esta sentencia se aplica a la tabla en s misma, nunca a la lnea de cabecera. El modo de ordenacin se especifca mediante el parmetro ASCENDING o DESCENDING, siendo el primero el que se realiza por defecto. En general, el sentido de la ordenacin depende de los campos de la clave de la tabla interna. La clave de ordenacin por defecto se hace con los campos no numricos de la lnea de la tabla en el orden en el que estn dispuestos. Cuanto ms grande sea la clave de ordenacin, ms tiempo necesitar el sistema para ordenar la tabla. Si sta adems contiene una tabla interna, el proceso de ordenacin puede ser considerablemente ms lento. Por otro lado, no nos es posible la ordenacin de tablas sorted, debido a que el sistema las mantiene ya ordenadas automticamente. Si aplicamos la sentencia SORT a una tabla sorted, aqulla causar un error de sintaxis.

7.8.1.- Ordenacin con otra clave


Si tenemos una tabla interna con un tipo de lnea estructutrado que queramos ordenar con una clave diferente de la de por defecto, podemos especifcarlo en la sentencia SORT:
SORT <itab> [ASCENDING|DESCENDING] [AS TEXT] [STABLE] BY <f1> [ASCENDING|DESCENDING] [AS TEXT] ... <fn> [ASCENDING|DESCENDING] [AS TEXT].

La tabla est ahora ordenada por los componentes especificados <f 1 > ... <f n > en lugar de estarlo por la clave de la tabla. El nmero de campos de ordenacin se limita a 250. Como en el anterior caso, el modo de ordenacin depende de la secuencia de los campos <f i >. La secuencia de ordenacin especificada antes de BY se aplica a todos los campos. La secuencia de ordenacin despus de un campo se aplica slo a esa columna de la tabla.

7.8.2.- Ordenacin alfabtica


Adems de los casos de ordenacin ascendente o descendente, sta puede ser alfabtica:
SORT <itab> ... AS TEXT ... .

Esta sentencia afecta a la ordenacin de cadenas de caracteres. Sin ella, dichas cedenas se ordenan de acuerdo con la secuencia especificada por la plataforma hardware del sistema. Con la opcin AS TEXT, el sistema ordena campos de caracteres alfabticamente de acuerdo con el entorno textual actual. Por defecto, dicho entorno textual se establece en el registro maestro del usuario. Sin embargo, tambin podemos especificarlo explcitamente usando la sentencia:
SET LOCALE LANGUAGE

La clusula AS TEXT nos ahorrar el tener que converitr cadenas a un formato de ordenacin compatible. Si AS TEXT se aplica a toda la ordenacin entera, sta slo afecta a los campos de tipo C. De ser aplicada a un campo concreto, ste ha de ser de tipo C, igualmente.

30

Tablas internas

7.9.- Determinacin de los atributos de una tabla interna


Para averiguar los atributos de una tabla interna en tiempo de ejecucin que no estn disponibles estticamente, debemos usar la sentencia:
DESCRIBE TABLE <itab> [LINES <l>] [OCCURS <n>] [KIND <k>].

Si usamos el parmetro LINES, el nmero de lneas rellenas se escribir en la variable <l>. Si usamos el parmetro OCCURS, el valor del tamao inicial de la tabla se escribir en la variable <n>. Si usamos el parmetro KIND, el tipo de tabla interna se devolver mediante la variable <k>: T para tablas estndar, S para tablas estndar y H para las hashed.
DATA: BEGIN OF LINE, COL1 TYPE I, COL2 TYPE I, END OF LINE. DATA ITAB LIKE HASHED TABLE OF LINE WITH UNIQUE KEY COL1 INITIAL SIZE 10. DATA: LIN TYPE I, INI TYPE I, KND TYPE C. DESCRIBE TABLE ITAB LINES LIN OCCURS INI KIND KND. WRITE: / LIN, INI, KND. DO 1000 TIMES. LINE-COL1 = SY-INDEX. LINE-COL2 = SY-INDEX ** 2. INSERT LINE INTO TABLE ITAB. ENDDO. DESCRIBE TABLE ITAB LINES LIN OCCURS INI KIND KND. WRITE: / LIN, INI, KND.

La salida sera:
0 1,000 10 10 H H

Aqu, se crea una tabla hashed que se rellena posteriormente. La sentencia DESCRIBE TABLE de procesa antes y despus del llenado de la tabla. El nmero de lneas actual cambia, no as el nmero de lneas inicial.

31