Skip to content

ABAP Keyword Documentation →  ABAP - Reference →  Processing External Data →  ABAP - Database Accesses →  Open SQL →  Open SQL - Read Accesses →  SELECT 

SELECT, Dynamic Token Specification

The example illustrates the dynamic Token specification in OpenSQL for the SELECT statement.

Other versions: 7.31 | 7.40 | 7.54

Source Code

    CONSTANTS left TYPE tabname VALUE 'SFLIGHT'.

    DATA: right         TYPE tabname,
          struct_type   TYPE REF TO cl_abap_structdescr,
          table_type    TYPE REF TO cl_abap_tabledescr,
          comp_tab1     TYPE cl_abap_structdescr=>component_table,
          comp_tab2     TYPE cl_abap_structdescr=>component_table,
          comp1         LIKE LINE OF comp_tab1,
          comp2         LIKE LINE OF comp_tab2,
          select        TYPE TABLE OF edpline,
          sublist       TYPE edpline,
          from          TYPE string,
          first_on      TYPE abap_bool VALUE abap_true,
          tref          TYPE REF TO data,
          alv           TYPE REF TO cl_salv_table.

    FIELD-SYMBOLS <itab> TYPE STANDARD TABLE.

    IF spfli = 'X'.
      right = 'SPFLI'.
    ELSEIF  scarr = 'X'.
      right = 'SCARR'.
    ELSEIF saplane = 'X'.
      right = 'SAPLANE'.
    ENDIF.

    first_on = abap_true.
    CLEAR: select, sublist, from.
    READ CURRENT LINE LINE VALUE INTO right.

    struct_type ?=
      cl_abap_typedescr=>describe_by_name( left ).
    comp_tab1 = struct_type->get_components( ).

    struct_type ?=
      cl_abap_typedescr=>describe_by_name( right ).
    comp_tab2 = struct_type->get_components( ).

    from = left && ` join ` && right && ` on `.

    LOOP AT comp_tab1 INTO comp1 WHERE name IS NOT INITIAL.
      sublist = left && '~' && comp1-name.
      APPEND sublist TO select.
    ENDLOOP.

    LOOP AT comp_tab2 INTO comp2 WHERE name IS NOT INITIAL.
      READ TABLE comp_tab1 INTO comp1
        WITH TABLE KEY name = comp2-name.
      IF sy-subrc <> 0.
        APPEND comp2 TO comp_tab1.
        sublist = right && '~' && comp2-name.
        APPEND sublist TO select.
      ELSE.
        IF first_on = abap_false.
          from = from && ` and `.
        ELSE.
          first_on = abap_false.
        ENDIF.
        from = from && left  && `~` && comp2-name &&
              ` = ` && right && `~` && comp2-name.
      ENDIF.
    ENDLOOP.

    struct_type = cl_abap_structdescr=>create( comp_tab1 ).
    table_type = cl_abap_tabledescr=>create( struct_type ).
    CREATE DATA tref TYPE HANDLE table_type.
    ASSIGN tref->* TO <itab>.

    SELECT (select) INTO TABLE <itab> FROM (from).

    TRY.
        cl_salv_table=>factory(
          IMPORTING r_salv_table = alv
          CHANGING  t_table      = <itab> ).
        alv->display( ).
      CATCH cx_salv_msg.
        MESSAGE 'ALV display not possible' TYPE 'I'
                DISPLAY LIKE 'E'.
    ENDTRY.

Description

After the program is started, a selection screen with the names of the tables SPFLI, SCARR, and SAPLANE is displayed. The user can select one of the tables, which is then linked to the table SFLIGHT in accordance with its foreign key relationship. This assumes that all fields with the same name have a foreign key relationship with each other. The content of the joined tables is displayed in an ALV Grid Control.

The selected table name is assigned to the field right. Initially, the RTTS class CL_ABAP_TYPEDESCR is used to determine the type description for the columns in the left and right table of the join. The method GET_COMPONENTS_SIMPLE is used to store these in two type description tables comp_tab1 or comp_tab2, which contain an entry for each column of the database table in question.

Then, a fragment of the FROM clause is created, which contains the names of the tables to be joined; the FROM clause is later completed using the ON conditions.

All columns of the left table should be entered in the SELECT list, as well as those columns of the right table for which no columns with the same name exist in the left table. The content of the type description tables is processed in loops.

Initially, the columns of the left table are processed. The current column is incorporated first into the dynamic SELECT list, which should be specified in the internal table select. The column name comp1-name is prefixed with the table name in left, to ensure its uniqueness. The statement MOVE-CORRESPONDING is used to copy the column description from comp_tab1 to an internal table comp_tab_join whose type is suitable for creating the objects later.

The columns of the right table are searched in the left table. If the column comp2-name only exists in the right table, it is, for the time being, incorporated into the type description table comp_tab_join. After that, it is added to all columns of the left table of the SELECT list select, just like before.

If the column in comp2-name exists in both tables, an ON condition that compares columns with the same name from the left and the right table, is added to the dynamic FROM clause from.

The type description table comp_tab_join and the static method CREATE of the class CL_ABAP_STRUCTDESCR can now be used to create a matching type object for the structure of the target area of the SELECT statement. This type object could now be specified after the addition TYPE HANDLE of the statement CREATE DATA to create a structured work area. However, we go one step further and use the method CREATE of the class CL_ABAP_TABLEDESCR to create a type object for an internal table of this row type and create this with CREATE DATA. By assigning the dynamically created internal tables to a field symbol <itab>, we create a name for the internal table that is useable in the INTO clause of the SELECT statement. Direct specification of a dereferencing tref->* in statements other than ASSIGN is only possible if tref is not generically typed. However, in our example, tref is generically typed with TYPE REF TO data.

Subsequently, the data is read with a completely dynamic SELECT statement. The content of the internal table <itab> is displayed dynamically using class CL_SALV_TABLE.