Objectives
After completing this lesson, you will be able to:
- Rellenar tablas internas complejas con datos.
- Acceder al contenido de tablas internas complejas.
- Utilice tablas internas complejas en ABAP SQL.
Relleno de tabla interna compleja
Como ya ha aprendido, la forma más sencilla de añadir una nueva fila a una tabla interna es la sentencia APPEND con un objeto de datos cuyo tipo corresponde al tipo de fila de la tabla interna. Este objeto de datos a veces se denomina área de trabajo.
Para tablas internas simples, el área de trabajo utilizada en APPEND puede ser una variable escalar, una constante o un literal. Para tablas internas complejas, el área de trabajo debe estar estructurada.
En el ejemplo, la conexión variable estructurada se utiliza para rellenar las conexiones de tabla internas.
En principio, existen dos formas de declarar la conexión del área de trabajo:
- Hacer referencia directa al tipo de fila st_connection
- Haga referencia al tipo de fila indirectamente mediante LIKE LINE OF <tabla_interna>.
La definición de áreas de trabajo con LIKE LINE OF tiene dos ventajas:
- Muestra el objetivo de la variable estructurada como área de trabajo para la tabla interna
- Garantiza que el área de trabajo se ajuste a la tabla interna, incluso si se modifica la definición de la tabla interna.
Si no rellena el área de trabajo antes de la sentencia APPEND, la nueva fila de la tabla interna se rellenará con valores iniciales específicos de tipo.
Consejo
Obtendrá el mismo resultado con la variante especial APPEND INITIAL LINE TO <internal_table>. Esta variante ni siquiera requiere un área de trabajo.
Para rellenar el área de trabajo estructurada, puede rellenar los componentes individuales o, como puede ver en el ejemplo, utilizar una expresión VALUE #( ).
Como puede ver en el ejemplo, también puede utilizar una expresión VALUE #( ) directamente en la sentencia APPEND. En este caso, no necesita un área de trabajo.
Nota
Esto puede tener un efecto positivo en el consumo global de memoria de su programa.
Existe una variante de la expresión VALUE #( ) que puede asignar directamente a una tabla interna. En esta variante de VALUE #( ) se utilizan pares adicionales de paréntesis para separar las filas de la tabla entre sí.
El ejemplo de código rellena los soportes de tabla internos con tres filas, cada uno con un valor diferente para carrier_id y carrier_name. Como resultado, la columna currency_code no se menciona, se rellena con el valor inicial específico del tipo.
Nota
Con la asignación anterior, todas las filas de tabla existentes se eliminan antes de que la tabla se rellene con las filas nuevas.
Para copiar datos entre campos con nombre idéntico de dos tablas internas, utilice el operador CORRESPONDING. Esto funciona de forma similar a CORRESPONDING para estructuras: para cada fila de la tabla interna de origen, el sistema crea una nueva fila en la tabla interna de destino y copia datos entre campos con el mismo nombre. Los campos fuente para los que no existe ningún campo con el mismo nombre en el destino no se copian. Los campos destino para los que no existe ningún campo con el mismo nombre en la fuente se rellenan con valores iniciales específicos de tipo.
En el ejemplo, los portadores de tabla internos de origen contienen tres filas. Por lo tanto, después de la valoración, las conexiones de tabla internas de destino también contienen tres filas.
Los campos carrier_id y carrier_name existen en ambas tablas internas. Se copian de origen a destino. El campo currency_code solo existe en la fuente. No se copia. Los campos connection_id, airport_from_id y airport_to_id solo existen en el destino. Se rellenan con valores iniciales.
Nota
Si la tabla interna de destino contiene datos antes de la asignación, el sistema los borra.
Cómo depurar tablas internas complejas
Pruébelo: llenando tablas internas complejas
- Como es el primer ejercicio de este curso, cree una nueva clase global que implemente la interfaz IF_OO_ADT_CLASSRUN.
- Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
TYPES: BEGIN OF st_connection,
carrier_id TYPE /dmo/carrier_id,
connection_id TYPE /dmo/connection_id,
airport_from_id TYPE /dmo/airport_from_id,
airport_to_id TYPE /dmo/airport_to_id,
carrier_name TYPE /dmo/carrier_name,
END OF st_connection.
TYPES tt_connections TYPE STANDARD TABLE OF st_connection
WITH NON-UNIQUE KEY carrier_id
connection_id.
DATA connections TYPE tt_connections.
TYPES: BEGIN OF st_carrier,
carrier_id TYPE /dmo/carrier_id,
carrier_name TYPE /dmo/carrier_name,
currency_code TYPE /dmo/currency_code,
END OF st_carrier.
TYPES tt_carriers TYPE STANDARD TABLE OF st_carrier
WITH NON-UNIQUE KEY carrier_id.
DATA carriers TYPE tt_carriers.
* Example 1: APPEND with structured data object (work area)
**********************************************************************
* DATA connection TYPE st_connection.
" Declare the work area with LIKE LINE OF
DATA connection LIKE LINE OF connections.
* connection-carrier_id = 'NN'.
* connection-connection_id = '1234'.
* connection-airport_from_id = 'ABC'.
* connection-airport_to_id = 'XYZ'.
* connection-carrier_name = 'My Airline'.
" Use VALUE #( ) instead assignment to individual components
connection = VALUE #( carrier_id = 'NN'
connection_id = '1234'
airport_from_id = 'ABC'
airport_to_id = 'XYZ'
carrier_name = 'My Airline' ).
APPEND connection TO connections.
out->write( `--------------------------------` ).
out->write( `Example 1: APPEND with Work Area` ).
out->write( connections ).
* Example 2: APPEND with VALUE #( ) expression
**********************************************************************
APPEND VALUE #( carrier_id = 'NN'
connection_id = '1234'
airport_from_id = 'ABC'
airport_to_id = 'XYZ'
carrier_name = 'My Airline'
)
TO connections.
out->write( `----------------------------` ).
out->write( `Example 2: Append with VALUE` ).
out->write( connections ).
* Example 3: Filling an Internal Table with Several Rows
**********************************************************************
carriers = VALUE #( ( carrier_id = 'AA' carrier_name = 'American Airlines' )
( carrier_id = 'JL' carrier_name = 'Japan Airlines' )
( carrier_id = 'SQ' carrier_name = 'Singapore Airlines')
).
out->write( `-----------------------------------------` ).
out->write( `Example 3: Fill Internal Table with VALUE` ).
out->write( carriers ).
* Example 4: Filling one Internal Table from Another
**********************************************************************
connections = CORRESPONDING #( carriers ).
out->write( `--------------------------------------------` ).
out->write( `Example 4: CORRESPONDING for Internal Tables` ).
out->write( data = carriers
name = `Source Table CARRIERS:`).
out->write( data = connections
name = `Target Table CONNECTIONS:`).
- Pulse CTRL + F3 en el teclado para activar la clase y F9 para ejecutar la aplicación de consola.
- Analice la salida de la consola. Depurar el programa, jugar con el código fuente para familiarizarse con los conceptos.
Acceso a tablas internas complejas
Anteriormente en este curso, aprendió a recuperar una sola fila de una tabla interna simple utilizando una expresión de tabla interna. En ese momento usamos un acceso a índice, es decir, identificamos la fila a través de su posición en la tabla interna. Este acceso mediante índice funciona para tablas internas complejas de la misma manera. Sin embargo, para tablas internas complejas, las expresiones de tabla interna con acceso clave se vuelven importantes, donde se identifica la fila a través de su contenido.
Nota
Aunque esto se denomina acceso clave, puede utilizar cualquier campo para la selección, no solo campos clave de la tabla interna. Si más de una fila cumple el requisito, las tablas ESTÁNDAR devuelven la primera fila, es decir, la fila con el índice más bajo.
El ejemplo lee una sola fila de las conexiones de tablas internas. La clave de esta tabla interna consta de campos, carrier_id y connection_id, pero el acceso clave utiliza airport_from_id y airport_to_id para identificar la fila. La tabla Interna contiene dos conexiones del aeropuerto SFO a SIN, por lo que se devuelve el primero de ellos.
Recuerde que el tiempo de ejecución ABAP genera la excepción CX_SY_ITAB_LINE_NOT_FOUND si ninguna de las filas cumple el requisito. Gestionar esta excepción en una estructura TRY … CATCH … ENDTRY para evitar errores en tiempo de ejecución
Para procesar varias líneas de una tabla interna especificando campos, utilice LOOP AT <tabla interna> INTO <destino> WHERE <condición>. La condición WHERE puede contener cualquier número de expresiones constituyentes unidas mediante AND y OR. Dentro de las expresiones, puede utilizar no solo el operador de igual (=), sino también los operadores >, >=, <, <=, <> y BETWEEN.
Después de leer el contenido de una fila de tabla en un área de trabajo, a veces desea volver a escribir las modificaciones del área de trabajo en la tabla interna. Una forma de hacerlo es la sentencia MODIFY TABLE.
Esta sentencia es un acceso clave porque el sistema utiliza el contenido de los campos clave en el área de trabajo para identificar la fila de la tabla que se debe modificar. A continuación, sobrescribe esta fila de tabla con el contenido del área de trabajo.
En el ejemplo, el área de trabajo transportista contiene el valor "JL" en el campo clave carrier_id. En función de este valor, el sistema identifica la segunda fila que se debe actualizar. Esta línea se actualiza con los valores del área de trabajo.
Nota
Solo puede modificar campos no clave con MODIFY TABLE. La sentencia no admite modificaciones en campos clave.
La sentencia MODIFY (sin palabra clave TABLE) no distingue entre campos clave y campos no clave. Sobrescribe toda la fila de la tabla con nuevos valores del área de trabajo. Esta sentencia se considera un acceso mediante índice porque la fila que se va a actualizar se identifica por su posición en la tabla interna. Normalmente, el índice se especifica explícitamente mediante la adición INDEX seguida de un argumento entero (literal, constante, variable, expresión).
Nota
También hay una variante especial sin añadir INDEX. Analizaremos esta variante a continuación.
En el ejemplo, la sentencia MODIFY utiliza el suplemento INDEX para direccionar la primera fila de la tabla. En esta fila, todos los campos se sobrescriben con los valores del área de trabajo, incluso el campo clave carrier_id.
A menudo habrá ocasiones en las que tendrá que modificar el contenido de varias filas de una tabla interna, o tal vez incluso todas. Para ello, implemente un loop sobre la tabla, que coloca cada fila que debe modificar sucesivamente en un área de trabajo. Dentro del loop, primero se modifica el contenido del área de trabajo y, a continuación, se vuelven a escribir las modificaciones en la tabla interna mediante la sentencia MODIFY.
Nota
Si no vuelve a escribir las modificaciones en la tabla, las modificaciones se perderán cuando el área de trabajo se rellene con los datos de la siguiente fila.
En el ejemplo, el loop lee todas las filas de portadores de tablas internas para las que aún no se ha rellenado el campo currency_code. Este es el caso de las dos últimas filas. Para cada una de estas filas, el programa sustituye el valor inicial en el campo currency_code por el nuevo valor "USD". Finalmente, utiliza la sentencia MODIFY para sobrescribir la fila actual con los valores actualizados.
En lugar de especificar el índice explícitamente, el ejemplo de código utiliza una forma breve de la sentencia MODIFY en la que falta el suplemento INDEX. Esta forma breve solo se permite entre LOOP … ENDLOOP. Solo allí el sistema puede actualizar implícitamente la fila en la que está trabajando actualmente.
Si utiliza MODIFY sin INDEX fuera de LOOP…ENDLOOP, el sistema no sabe qué fila modificar y desencadena un error de tiempo de ejecución no interceptable. Para evitar estos errores en tiempo de ejecución, asegúrese de no ignorar el mensaje de advertencia relacionado de la verificación de sintaxis.
Pruébelo: Acceso a tablas internas complejas
- Al igual que con el primer ejercicio de este curso, cree una nueva clase global que implemente la interfaz, IF_OO_ADT_CLASSRUN.
- Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
TYPES: BEGIN OF st_connection,
carrier_id TYPE /dmo/carrier_id,
connection_id TYPE /dmo/connection_id,
airport_from_id TYPE /dmo/airport_from_id,
airport_to_id TYPE /dmo/airport_to_id,
carrier_name TYPE /dmo/carrier_name,
END OF st_connection.
TYPES tt_connections TYPE SORTED TABLE OF st_connection
WITH NON-UNIQUE KEY carrier_id
connection_id.
DATA connections TYPE tt_connections.
DATA connection LIKE LINE OF connections.
TYPES: BEGIN OF st_carrier,
carrier_id TYPE /dmo/carrier_id,
currency_code TYPE /dmo/currency_code,
END OF st_carrier.
DATA carriers TYPE STANDARD TABLE OF st_carrier
WITH NON-UNIQUE KEY carrier_id.
DATA carrier LIKE LINE OF carriers.
* Preparation: Fill internal tables with data
**********************************************************************
connections = VALUE #( ( carrier_id = 'JL'
connection_id = '0408'
airport_from_id = 'FRA'
airport_to_id = 'NRT'
carrier_name = 'Japan Airlines'
)
( carrier_id = 'AA'
connection_id = '0017'
airport_from_id = 'MIA'
airport_to_id = 'HAV'
carrier_name = 'American Airlines'
)
( carrier_id = 'SQ'
connection_id = '0001'
airport_from_id = 'SFO'
airport_to_id = 'SIN'
carrier_name = 'Singapore Airlines'
)
( carrier_id = 'UA'
connection_id = '0078'
airport_from_id = 'SFO'
airport_to_id = 'SIN'
carrier_name = 'United Airlines'
)
).
carriers = VALUE #( ( carrier_id = 'SQ'
currency_code = ' '
)
( carrier_id = 'JL'
currency_code = ' '
)
( carrier_id = 'AA'
currency_code = ' '
)
( carrier_id = 'UA'
currency_code = ' '
)
).
* Example 1: Table Expression with Key Access
**********************************************************************
out->write( `--------------------------------------------` ).
out->write( `Example 1: Table Expressions with Key Access` ).
out->write( data = connections
name = `Internal Table CONNECTIONS: ` ).
" with key fields
connection = connections[ carrier_id = 'SQ'
connection_id = '0001' ].
out->write( data = connection
name = `CARRIER_ID = 'SQ' AND CONNECTION_ID = '001':` ).
" with non-key fields
connection = connections[ airport_from_id = 'SFO'
airport_to_id = 'SIN' ].
out->write( data = connection
name = `AIRPORT_FROM_ID = 'SFO' AND AIRPORT_TO_ID = 'SIN':` ).
* Example 2: LOOP with key access
**********************************************************************
out->write( `-------------------------------` ).
out->write( `Example 2: LOOP with Key Access` ).
LOOP AT connections INTO connection
WHERE airport_from_id <> 'MIA'.
"do something with the content of connection
out->write( data = connection
name = |This is row number { sy-tabix }: | ).
ENDLOOP.
* Example 3: MODIFY TABLE (key access)
**********************************************************************
out->write( `-----------------------------------` ).
out->write( `Example 3: MODIFY TABLE (key access` ).
out->write( data = carriers
name = `Table CARRRIERS before MODIFY TABLE:`).
carrier = carriers[ carrier_id = 'JL' ].
carrier-currency_code = 'JPY'.
MODIFY TABLE carriers FROM carrier.
out->write( data = carriers
name = `Table CARRRIERS after MODIFY TABLE:`).
* Example 4: MODIFY (index access)
**********************************************************************
out->write( `--------------------------------` ).
out->write( `Example 4: MODIFY (index access)` ).
carrier-carrier_id = 'LH'.
carrier-currency_code = 'EUR'.
MODIFY carriers FROM carrier INDEX 1.
out->write( data = carriers
name = `Table CARRRIERS after MODIFY:`).
* Example 5: MODIFY in a LOOP
**********************************************************************
out->write( `----------------------------` ).
out->write( `Example 5: MODIFY in a LOOP` ).
LOOP AT carriers INTO carrier
WHERE currency_code IS INITIAL.
carrier-currency_code = 'USD'.
MODIFY carriers FROM carrier.
ENDLOOP.
out->write( data = carriers
name = `Table CARRRIERS after the LOOP:`).
- Pulse CTRL + F3 en el teclado para activar la clase y F9 para ejecutar la aplicación de consola.
- Analice la salida de la consola. Depurar el programa, jugar con el código fuente para familiarizarse con los conceptos.
Tablas internas complejas en ABAP SQL
La sentencia ABAP SQL, SELECT, lee datos de una tabla de base de datos o una vista CDS. Cuando utiliza la opción SINGLE, se lee exactamente un registro de la base de datos, incluso si existen más datos que cumplan las condiciones de la cláusula WHERE.
Como aprendió anteriormente, una forma de recibir este resultado de registro individual es la variable estructurada después de la palabra clave INTO.
Si utiliza SELECT sin SINGLE, indica que está interesado en todos los registros que coinciden con las condiciones de la cláusula WHERE. A continuación, debe asegurarse de que realmente puede recibir y almacenar varios registros. La forma obvia de hacerlo es el uso de una tabla interna compleja como destino de la sentencia SELECT. Esto es posible, pero requiere añadir TABLE entre la palabra clave INTO y el nombre de la tabla interna.
En el ejemplo, queremos leer los tres aeropuertos relacionados con Londres y no solo uno de ellos. Por lo tanto, excluimos la palabra clave SINGLE después de SELECT, añadimos la palabra clave TABLE después de INTO y utilizamos la tabla interna airports_full como destino de la sentencia SELECT.
El ejemplo utiliza una lista de campos explícita después de FIELDS que coincide con las columnas de la tabla interna airports_full. Por supuesto, también puede utilizar FIELDS *, INTO CORRESPONDING FIELDS OF TABLE y nombres alias en la lista de campos.
Este ejemplo utiliza FIELDS * en lugar de una lista de campos explícita e INTO CORRESPONDING FIELDS OF TABLE en lugar de INTO TABLE.
Como el tipo de fila de la tabla interna Aeropuertos contiene solo dos componentes AirportID y Name, solo los campos con el mismo nombre se leen de la base de datos.
Si utiliza DATA( ) en una sentencia SELECT después del suplemento INTO TABLE, declara en línea una tabla interna. El tipo de fila de esta tabla interna se deriva de la cláusula FIELDS. Para los campos de tabla y los elementos de vista, un nombre de alias es opcional. Para expresiones en la cláusula FIELDS, un nombre de alias es obligatorio si la cláusula INTO contiene una declaración en línea.
Nota
Las declaraciones en línea de tablas internas solo se admiten después de INTO TABLE. No puede utilizar declaraciones en línea después de INTO CORRESPONDING FIELDS OF TABLE.
Las tablas internas declaradas en línea siempre son tablas estándar sin clave. No puede declarar tablas clasificadas o de claves de control mediante declaraciones en línea. Esto puede causar problemas de rendimiento si rellena la tabla interna con muchas filas y utiliza mucho el acceso mediante clave.
Cuando lee varios registros de la base de datos, algunas técnicas SQL especiales se vuelven especialmente interesantes. Una de estas técnicas es la directiva UNION para combinar los resultados de varias sentencias SELECT.
La figura ilustra la combinación de dos resultados SELECT:
El primer resultado SELECT lee ID y NAME de todos los transportistas con CurrencyCode = 'GBP'. La segunda SELECT lee ID y NAME de todos los aeropuertos con City = 'London'. La primera SELECT devuelve un registro, la segunda SELECT devuelve tres registros. En lugar de recuperar estos resultados por separado, se combinan en un resultado con cuatro registros. Es importante señalar que esto ocurre dentro de la base de datos.
Un requisito previo para esta técnica es, por supuesto, que los dos resultados sean compatibles entre sí, es decir, que tengan el mismo número de campos y los mismos nombres de campo. Es beneficioso, aunque no necesario, que los tipos de campos también sean los mismos.
La sintaxis ABAP SQL para este ejemplo consta de dos sentencias SELECT. Cada sentencia SELECT tiene su propia cláusula FROM, cláusula FIELDS y cláusula WHERE, pero solo hay una cláusula INTO al final. Las dos sentencias SELECT están conectadas por las palabras clave UNION ALL.
Nota
Con UNION en lugar de UNION ALL, la base de datos buscaría y eliminaría duplicados antes de devolver el resultado. Utilizamos UNION ALL para evitar esta carga adicional innecesaria en la base de datos.
Ambas listas de campos constan de tres elementos, el primer y el segundo elemento tienen nombres alias idénticos en ambas cláusulas FIELDS. El tercer campo no necesita un alias porque el nombre del campo es el mismo en ambas vistas CDS.
Nota
El primer elemento en FIELDS es un texto literal que nos permite distinguir entre aerolíneas y aeropuertos en el resultado combinado.
Pruébelo: Tablas internas en ABAP SQL
- Como en el primer ejercicio de este curso, cree una nueva clase global que implemente la interfaz IF_OO_ADT_CLASSRUN.
- Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
TYPES: BEGIN OF st_airport,
airportid TYPE /dmo/airport_id,
name TYPE /dmo/airport_name,
END OF st_airport.
TYPES tt_airports TYPE STANDARD TABLE OF st_airport
WITH NON-UNIQUE KEY airportid.
DATA airports TYPE tt_airports.
* Example 1: Structured Variables in SELECT SINGLE ... INTO ...
**********************************************************************
DATA airport_full TYPE /DMO/I_Airport.
SELECT SINGLE
FROM /DMO/I_Airport
FIELDS AirportID, Name, City, CountryCode
WHERE City = 'Zurich'
INTO @airport_full.
out->write( `-------------------------------------` ).
out->write( `Example 1: SELECT SINGLE ... INTO ...` ).
out->write( data = airport_full
name = `One of the airports in Zurich (Structure):` ).
* Example 2: Internal Tables in SELECT ... INTO TABLE ...
**********************************************************************
DATA airports_full TYPE STANDARD TABLE OF /DMO/I_Airport
WITH NON-UNIQUE KEY AirportID.
SELECT
FROM /DMO/I_Airport
FIELDS airportid, Name, City, CountryCode
WHERE City = 'London'
INTO TABLE @airports_full.
out->write( `------------------------------------` ).
out->write( `Example 2: SELECT ... INTO TABLE ...` ).
out->write( data = airports_full
name = `All airports in London (Internal Table):` ).
* Example 3: FIELDS * and INTO CORRESPONDING FIELDS OF TABLE
**********************************************************************
SELECT
FROM /DMO/I_Airport
FIELDS *
WHERE City = 'London'
INTO CORRESPONDING FIELDS OF TABLE @airports.
out->write( `----------------------------------------------------------` ).
out->write( `Example 3: FIELDS * and INTO CORRESPONDING FIELDS OF TABLE` ).
out->write( data = airports
name = `Internal Table AIRPORTS:` ).
* Example 4: Inline Declaration
**********************************************************************
SELECT
FROM /DMO/I_airport
FIELDS AirportID, Name AS AirportName
WHERE City = 'London'
INTO TABLE @DATA(airports_inline).
out->write( `----------------------------------------------------------` ).
out->write( `Example 4: Inline Declaration after INTO TABLE` ).
out->write( data = airports_inline
name = `Internal Table AIRPORTS_INLINE:` ).
** Example 4: ORDER BY and DISTINCT
***********************************************************************
*
* SELECT
* FROM /DMO/I_Airport
* FIELDS DISTINCT CountryCode
* ORDER BY CountryCode
* INTO TABLE @DATA(countryCodes).
*
* out->write( countryCodes ).
* Example 5: UNION (ALL)
**********************************************************************
SELECT FROM /DMO/I_Carrier
FIELDS 'Airline' AS type, AirlineID AS Id, Name
WHERE CurrencyCode = 'GBP'
UNION ALL
SELECT FROM /DMO/I_Airport
FIELDS 'Airport' AS type, AirportID AS Id, Name
WHERE City = 'London'
* ORDER BY type, Id
INTO TABLE @DATA(names).
out->write( `----------------------------------------------` ).
out->write( `Example 5: UNION ALL of Airlines and Airports ` ).
out->write( data = names
name = `ID and Name of Airlines and Airports:` ).
- Pulse CTRL + F3 en el teclado para activar la clase y F9 para ejecutar la aplicación de consola.
- Analice la salida de la consola. Depurar el programa, jugar con el código fuente para familiarizarse con los conceptos.
Utilizar una tabla interna compleja
En este ejercicio, declara un atributo en forma de tabla, lo rellena con una sentencia SELECT y accede al contenido.
Tarea 1: Copiar plantilla
Copie la clase de modelo. Como alternativa, copie la solución del ejercicio anterior.
Pasos
Copie la clase /LRN/CL_S4D400_STS_STRUCTURE en una clase de su propio paquete (nombre sugerido: ZCL_##_ITAB, donde ## representa su número de grupo).
Abra el código fuente de la clase global /LRN/CL_S4D400_STS_STRUCTURE.
Vincule la vista Explorador de proyectos con el editor.
En la vista Explorador de proyectos, haga clic con el botón derecho en la clase /LRN/CL_S4D400_STS_STRUCTURE para abrir el menú contextual.
En el menú contextual, seleccione Duplicar ....
Introduzca el nombre del paquete en el campo Paquete. En el campo Nombre, introduzca el nombre ZCL_##_ITAB, donde ## representa su número de grupo.
Ajuste la descripción y seleccione Siguiente.
Confirme la orden de transporte y seleccione Finalizar.
Tarea 2: Declarar una tabla interna
En la clase local, declare aeropuertos de atributo estáticos en forma de tabla para almacenar información detallada en todos los aeropuertos disponibles. Comience definiendo un tipo de estructura privada st_airport y un tipo de tabla tt_airport dentro de la clase local.
Pasos
Cambie a la clase local lcl_connection.
En la clase global, seleccione Tipos locales.
Defina un tipo de estructura privadast_airport con los siguientes componentes:
Componentes del tipo de estructura st_airport:
| Nombre de componente | Tipo de datos |
|---|
| ID de aeropuerto | /dmo/airport_id |
| Nombre | /dmo/airport_name |
Ajuste el código de la siguiente manera:
1234567891011121314
TYPES:
BEGIN OF st_details,
DepartureAirport TYPE /dmo/airport_from_id,
DestinationAirport TYPE /dmo/airport_to_id,
AirlineName TYPE /dmo/carrier_name,
END OF st_details.
TYPES:
BEGIN OF st_airport,
AirportId TYPE /dmo/airport_id,
Name TYPE /dmo/airport_name,
END OF st_airport.
Defina un tipo de tabla privadatt_airport con las siguientes propiedades:
Propiedades del tipo de tabla tt_airport:
| Propiedad | Valor |
|---|
| Tipo de línea | st_airport |
| Clase de tabla | TABLA STANDARD |
| Definición de claves | CLAVE PREDETERMINADA NO ÚNICA |
Ajuste el código de la siguiente manera:
12345678910
TYPES:
BEGIN OF st_airport,
AirportId TYPE /dmo/airport_id,
Name TYPE /dmo/airport_name,
END OF st_airport.
TYPES tt_airports TYPE STANDARD TABLE OF st_airport
WITH NON-UNIQUE DEFAULT KEY.
Declare un nuevo atributo estático privado aeropuertos y escríbalo con el tipo de tabla tt_aeropuertos.
Al final de la definición de clase, añada el siguiente código:
123
CLASS-DATA airports TYPE tt_airports.
Tarea 3: Rellenar el atributo estático en un constructor de clase
Defina un constructor de clase e implemente una sentencia SELECT que lea todos los aeropuertos disponibles de la entidad de vista CDS /DMO/I_Airport en el atributo estático aeropuertos.
Pasos
Añada un constructor de clase a la clase local lcl_connection mediante una corrección rápida.
Sitúe el cursor en el nombre de la clase y pulse Ctrl + 1.
Haga doble clic en Generar constructor de clase.
En el constructor de clase, implemente una sentencia SELECT que lea todos los conjuntos de datos de la entidad de vista CDS /DMO/I_Airport en los aeropuertos de atributos estáticos.
Navegue a la implementación del método class_constructor.
Dentro de la implementación del método, añada el siguiente código:
12345
SELECT FROM /DMO/I_Airport
FIELDS AirportID, Name
INTO TABLE @airports.
Tarea 4: Acceder al contenido de la tabla interna
Utilice el contenido de la tabla interna Aeropuertos en el método get_output para añadir los nombres de los aeropuertos a la salida.
Pasos
Navegue a la implementación del método get_output.
Continúe como lo ha hecho en los ejercicios anteriores.
Al principio del método, lea los detalles del aeropuerto de salida en un objeto de datos estructurado Salida.
Consejo
Utilice una expresión de tabla airports[ ... ] y una declaración en línea para la salida del objeto de datos.
Al principio del método, añada el siguiente código:
123
DATA(departure) = airports[ airportID = details-departureairport ].
De forma similar, lea los detalles del aeropuerto de destino en un destino de objeto de datos estructurado.
Ajuste el código de la siguiente manera:
1234
DATA(departure) = airports[ airportID = details-departureairport ].
DATA(destination) = airports[ airportID = details-destinationairport ].
Utilice el nombre de componente de las dos estructuras para añadir los nombres de aeropuerto a la salida.
Ajuste el código de la siguiente manera:
1234
APPEND |Departure: { details-departureairport } { departure-name }| TO r_output.
APPEND |Destination: { details-destinationairport } { destination-name }| TO r_output.
Opcional: Omita el objeto de datos estructurado y utilice las expresiones de tabla directamente en los modelos de string.
Comente las líneas de código en las que rellena las estructuras de salida y destino.
En el modelo de cadena, sustituya departure-name por airports[ airportid = details-departureairport ]-name.
De forma similar, sustituya destination-name por airports[ airportid = details-destinationairport ]-name.
Active la clase. Ejecútelo y analice la salida de la consola. Verifique que la salida muestre datos para todos los atributos.
Pulse Ctrl + F3 para activar la clase.
Pulse F9 para ejecutar la clase.