I had a problem in work where I would be selecting from tables that are decided on run time and also the where conditions on these tables are to be decided on run time. I found a lot of examples where one could create a dynamic internal table using the RTTS for INTO clause of SELECT. This was only half the solution to my problem. i still have to dynamically create as many where conditions as possible. The syntax of a dynamic select is:
We have four components in the above SQL query that can be given at run time:SELECT (columns) INTO CORRESPONDING FIELDS OF TABLE (Internal Table Name)FROM (Table Name)WHERE (Where String containing conditions)
- Columns. We don’t worry about this as the clause ‘INTO CORRESPONDING FIELDS’ will only pick the fields that are common in the internal table and the database table.
- Internal Table: This is achieved by following the example here.
- Table name: The calling service knows what table to select from.
- Where string containing conditions: This is the problem that is to be solved!
What I intend to do is let the calling program send me any number of ranges and its respective column name. So there will be an internal table (RANGES_TABLE) of the following structure:
Taking the example of table T001:BEGIN OF ranges_tables,tablename TYPE tabname16,fieldname TYPE fieldname,range TYPE REF TO data,END OF ranges_table.
Let’s populate RANGES_TABLE with two criteria, ORT01 and LAND1. We want to get table entries where ORT01 = ‘Walldorf’ and LAND1 = ‘DE’.
RANGES_TABLE now has a list of columns that we need to select from with the conditions respectively. But the user can send one column or two columns or (n) columns. This is will be solved by dynamically creating a structure that will have fields referring to different ranges. The structure will look like this:* 1* Create range for ORT01s_ort01-sign = 'I'.s_ort01-option = 'EQ'.s_ort01-low = 'Walldorf'.APPEND s_ort01 TO r_ort01.* Add entry in the Ranges tables_ranges_table-tablename = 'T001'.s_ranges_table-fieldname = 'ORT01'.CREATE DATA s_ranges_table-range LIKE r_ort01.ASSIGN s_ranges_table-range->* TO <range>.<range> = r_ort01.APPEND s_ranges_table TO t_range_table.* 2* Create range for LAND1s_land1-sign = 'I'.s_land1-option = 'EQ'.s_land1-low = 'DE'.APPEND s_land1 TO r_land1.* Add entry in the Ranges tables_ranges_table-tablename = 'T001'.s_ranges_table-fieldname = 'LAND1'.CREATE DATA s_ranges_table-range LIKE r_land1.ASSIGN s_ranges_table-range->* TO <range>.<range> = r_land1.APPEND s_ranges_table TO t_range_table.
Having creating a structure we create dynamic where conditions. So now the select query will be as follows:BEGIN OF select_strucfield1 TYPE range1..fieldn TYPE rangenEND OF select_struc
Here is the full list of the method that does all this:SELECT * INTO TABLE <l_rows>FROM (s_ranges_table-tablename)WHERE field1 IN select_struc-field1..AND fieldn IN select_struc-fieldn
METHOD select_from_ranges.DATA:l_index TYPE i,l_t_dyn_field TYPE abap_component_tab,l_s_dyn_field LIKE LINE OF l_t_dyn_field,l_str_range_name TYPE string,l_str_sel_option TYPE string,l_o_structdescr TYPE REF TO cl_abap_structdescr,l_d_range_str TYPE REF TO data,l_s_table_range LIKE LINE OF i_t_range.FIELD-SYMBOLS:<l_rows> TYPE ANY TABLE,<l_dyn_range_str> TYPE ANY,<l_range_tbl> TYPE table,<l_range_tbl2> TYPE table.* For all the where conditions sent* create fields in the select strucutureLOOP AT i_t_range INTO l_s_table_range._index = sy-tabix.ASSIGN l_s_table_range-range->* TO <l_range_tbl>.* Create dynamic fieldCLEAR:l_s_dyn_field.l_s_dyn_field-name = l_s_table_range-fieldname.l_s_dyn_field-type ?= cl_abap_datadescr=>describe_by_data( <l_range_tbl> ).APPEND l_s_dyn_field TO l_t_dyn_field.CONCATENATE '<l_dyn_range_str>-' l_s_table_range-fieldname INTO l_str_range_name.* More than one where requires in ANDIF l_index > 1.CONCATENATE l_str_sel_option 'AND'INTO l_str_sel_option SEPARATED BY space.ENDIF.CONCATENATE l_str_sel_option l_s_table_range-fieldname 'in' l_str_range_nameINTO l_str_sel_option SEPARATED BY space.ENDLOOP.* Create dynamic structure with fields pointing to different rangel_o_structdescr = cl_abap_structdescr=>create( p_components = l_t_dyn_field ).CREATE DATA l_d_range_str TYPE HANDLE l_o_structdescr.ASSIGN l_d_range_str->* TO <l_dyn_range_str>.* For all the fields in the structure point them to the range tablesWHILE sy-subrc IS INITIAL.ASSIGN COMPONENT sy-index OF STRUCTURE <l_dyn_range_str> TO <l_range_tbl2>.IF sy-subrc IS NOT INITIAL.EXIT.ENDIF.READ TABLE i_t_range INTO l_s_table_range INDEX sy-index.ASSIGN l_s_table_range-range->* TO <l_range_tbl>.<l_range_tbl2> = <l_range_tbl>.ENDWHILE.ASSIGN c_rows->* TO <l_rows>.* Select from the tableSELECT * INTO TABLE <l_rows>FROM (l_s_table_range-tablename)WHERE (l_str_sel_option).ENDMETHOD.
No comments:
Post a Comment