rootbin

总是很懒,写不来博客,最近发现可以从onenote同步到博客园,虽然格式丑点,勉强算写博客了吧,可能以后都不干abap,权当纪念一下.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

简单的查询分析器

Posted on 2013-04-28 15:05  rootbin  阅读(383)  评论(0)    收藏  举报

se16n,只能用来查一张表的数据

每每想到以前用的查询分析器或者各种Console就忍不住想吐槽

刚开始接触abap的时候就想自己写一个查询分析器

这两天周六周日上班,不想干活…

尝试着开始写这个东西

趁放假前把写好的东西放出来吧

实现了简单的查询 及 连接查询  (增删改暂时不支持,可以考虑根据关键字进行操作的分类,应该也是类似的)

(个人估计 五一后也没这么多精力来做这种东西了  这是第一个版本 也是最后一个版本了

虽然写的有点挫  部分代码都是copy过来后都没怎么改  所以比较凌乱  但单大致思路应该还是可以的)

 

主要使用的技术:

1. “自省”结构体:  主要是某个表结构的所有字段

2. 动态内表

3. 动态程序

 

现在的程序有个BUG:

P类型数据, 采用的技术手段获取字段信息不准确

例如 domain中定义的是 length 13 decimals 3  但是现在获取的是  length 7  decimals 2

导致select数据在添加到动态内表时,由于结构不一致,导致异常…

 

效果截图:

a.查询语句:

image

b.结果:

image

 

附:代码

REPORT  Z_QUERY_PARSER.
type-pools: esp1,abap .
tables: mara.
data: gt_message type ESP1_MESSAGE_TAB_TYPE with header line.
data: gt_sql LIKE abapsource OCCURS 0 WITH HEADER LINE.

*每个筛选字段  例如:mara~matnr
types: begin of field_value,
        value(20),
       end of field_value.

data: gt_field type field_value occurs 0 with header line.
data: gt_component type field_value occurs 0 with header line.
data: gt_tabname type field_value occurs 0 with header line.

perform call_query_panel.
perform spliter.
perform create_dyn_pro.


form call_query_panel.

   CALL FUNCTION 'EDITOR_APPLICATION'
       EXPORTING
            application = 'BF'
            display     = ' '
            name        = 'Query Panel'
*       IMPORTING
*            fcode       = fcode
*            changed     = changed
       TABLES
            content     = gt_sql[].
endform.

form spliter.
  data: l_query type string.
  data: l_field(10),l_tabname1(10),l_tabname2(10).
  loop at gt_sql.
    concatenate l_query gt_sql  into l_query separated by space.
  endloop.

  condense l_query.
  translate l_query to upper case.
  split l_query at space into table gt_field.
endform.


form create_dyn_pro.
DATA: l_prog TYPE string,
      l_code  TYPE STANDARD TABLE OF string with header line,
      l_mess TYPE string,
      l_sid  TYPE string.
data: l_query_string type string.
data: l_state(1),lt_temp type standard table of string with header line.
field-symbols: <dyn_field> type any,
               <comp_wa> TYPE abap_compdescr    .
data: ref_wa type ref to data,
      descr_ref TYPE REF TO cl_abap_structdescr.

data: lt_compdes type abap_compdescr occurs 0 with header line.

*1.确定筛选的字段
loop at gt_field.
  if gt_field-value = 'SELECT'.
    continue.
  endif.

  if gt_field-value = 'FROM'.
    EXIT.
  endif.

  gt_component-value = gt_field-value.
  if gt_component-value cs '~'.
    clear lt_temp[].
    split gt_component-value at '~' into table lt_temp.
    read table lt_temp index 2.
    gt_component-value = lt_temp.
  endif.
  append gt_component.clear gt_component.

endloop.

*2.涉及的tables
loop at gt_field.
  if gt_field-value = 'FROM' or gt_field-value = 'JOIN'.
    l_state = 'X'.
    continue.
  endif.

  if l_state = 'X'.
    gt_tabname-value = gt_field-value.
    append gt_tabname.clear gt_tabname.
    l_state = ''.
  endif.

endloop.

write / '===================================='.
write / 'Components:'.
write / ''.
loop at gt_component.
  write  gt_component-value.
endloop.
write / '===================================='.
write / 'Tables:'.
loop at gt_tabname.
  write / gt_tabname-value.
endloop.
write / '===================================='.
write / 'Results:'.
append 'PROGRAM subpool.'  TO l_code.

*定义数据表
loop at gt_tabname.
  concatenate 'tables:' gt_tabname '.' into l_code.
  append l_code.
endloop.

*添加动态数据的定义
append `field-symbols: <dyn_table> type standard table ,` &
              `<dyn_wa> type any,` &
               `<dyn_field> type any.`  to l_code.

append `data: dy_table type ref to data, ` &
       ` wa_line type ref to data. ` to l_code.


append `data: it_structure type lvc_t_fcat,` &
      `wa_structure type lvc_s_fcat.` to l_code.


loop at gt_tabname.
*根据涉及的数据表结构 动态构造存放结果的内表
  create data ref_wa type (gt_tabname-value).
  assign ref_wa->* to <dyn_field>.
  descr_ref ?= cl_abap_typedescr=>describe_by_data( <dyn_field> ).
  LOOP AT descr_ref->components ASSIGNING <comp_wa>.
    append <comp_wa> to lt_compdes.
  ENDLOOP.
endloop.

*删除重复字段  防止异常
sort lt_compdes by name .
delete adjacent duplicates from lt_compdes.

append 'form dyn_form.' to l_code.
*加入创建动态内表的code
data l_temp(3) type n.
loop at lt_compdes.
    concatenate `wa_structure-fieldname = '` lt_compdes-name `'.` into  l_code separated by space.
    append l_code.

    concatenate `wa_structure-inttype = '` lt_compdes-type_kind  `'.` into l_code separated by space.
    append l_code.
    l_temp = lt_compdes-length.
    concatenate `wa_structure-intlen = '` l_temp `'.` into l_code separated by space.
    append l_code.
    l_temp = lt_compdes-decimals.
    concatenate `wa_structure-decimals_o = '` l_temp `'.` into l_code separated by space.
    append l_code.
    append `append wa_structure to it_structure.` to l_code.
endloop.

append `CALL METHOD cl_alv_table_create=>create_dynamic_table ` &
       ` EXPORTING ` &
       ` it_fieldcatalog = it_structure  ` &
       ` IMPORTING ` &
       ` ep_table        = dy_table . ` to l_code.
append ` assign dy_table->* to <dyn_table>.` to l_code.

append ` create data wa_line like line of <dyn_table>. ` to l_code.
append ` assign wa_line->* to <dyn_wa>. ` to l_code.

loop at gt_field.
  if gt_field-value = 'WHERE'.
    concatenate l_query_string 'into corresponding fields of table <dyn_table>' 'where' into l_query_string separated by space.
  else.
    concatenate l_query_string gt_field-value  into l_query_string separated by space.
  endif.
endloop.
append '.' to l_code.

append l_query_string to l_code.
append `loop at <dyn_table> assigning <dyn_wa>.` to l_code.
append `write / ''.` to l_code.

  loop at gt_component.
    concatenate `'` gt_component-value `'` into gt_component-value.
    concatenate 'assign component' gt_component-value 'of structure <dyn_wa> to <dyn_field>.'
      into l_code separated by space.
    append l_code.
    append `write <dyn_field>.` to l_code.
  endloop.
append `endloop.` to l_code.
append 'endform.' to l_code.

GENERATE SUBROUTINE POOL l_code NAME l_prog
         MESSAGE l_mess
         SHORTDUMP-ID l_sid.

IF sy-subrc = 0.
  PERFORM ('DYN_FORM') IN PROGRAM (l_prog) IF FOUND.
ELSEIF sy-subrc = 4.
  MESSAGE l_mess TYPE 'I'.
ELSEIF sy-subrc = 8.
  MESSAGE l_sid TYPE 'I'.
ENDIF.

endform.


亲爱的P.I.G 你应该是不会到这里来的吧 ? I'm always 怀挺!