zoukankan      html  css  js  c++  java
  • [SAP ABAP开发技术总结]逻辑数据库

    LDB不常用,但学好它可以写出共用封装好的查询

    6.   逻辑数据库

    6.1.  组成

    SLDB

    image049 

    6.2.  结构

    image050

    决定了数据从哪些数据库表、视图中提取数据以及这些表、视图之间的层次关系(层次将决定数据读取的顺序

    数据库表T类型节点)、词典类型S类型节点),比如节点类型为S的节点:root_node,数据类型为INT4

    image051

    LDB的数据库程序的最TOP Include文件包括以下语句:

     NODES root_node.

    另外,在LDB数据库程序包括了以下过程:

    FORM put_root_node.
     
    DO 10 TIMES.
        root_node
    = sy-index.
       
    PUT root_node."会去调用报表程序中的 GET root_node. 事件块
     
    ENDDO.
    ENDFORM.

    在与此LDB关连的可执行程序:

    image052

    REPORT demo_nodes.
    NODES root_node.
    GET root_node. 
     
    WRITE root_node.

    6.3.  选择屏幕(Selections

    定义了LDB的选择屏幕,该选择屏幕的布局由LDB的结构决定,一旦将LDB链接到报表程序后,该选择屏幕会自动嵌入到默认选择屏幕1000

    image050[1]

    第一次进入选择屏幕程序时,系统会为每个LDB生成一个名为DB<LDB_Name>SELInclude选择屏幕包含文件:

    image053

    image054

     

    而且,所有表(T类型的节点)的主键都会出现在SELECT-OPTIONS语句中,成为屏幕选择字段(自动生成的需要去掉注释,并设置屏幕选择字段名):

    image055

    除了上面自动生成的LDB屏幕字段外,还可以使用以下面语句来扩展LDB选择屏幕:

    6.3.1.   PARAMETERS屏幕参数扩充

    增加一个单值输入条件框(PARAMETERS语句一般在LDB中只用于除节点表外的非表字段屏幕参数),在PARAMETERS语句中必须使用选项FOR NODE XXX 或者 FOR TABLE XXX 来指定这些扩展参数属性哪个节点的:PARAMETERS CITYTO LIKE SPFLI-CITYTO FOR NODE SPFLI.

    注:SELECT-OPTIONS没有FOR NODE这样的用法

    具体请参数后面的LDB选择屏幕章节

    6.3.2.   SELECTION-SCREEN格式化屏幕

    使用SELECTION-SCREEN语句来格式化屏幕

    具体请参数后面的LDB选择屏幕章节

    6.3.3.   DYNAMIC SELECTIONS动态选择条件

    SELECTION-SCREEN DYNAMIC SELECTIONS FOR NODE|TABLE <node>.用来开启<node>节点的LDB dynamic selections功能,即可以在WHERE从句中使用动态选择条件(形如:…WHERE field1 = value1 AND (条件内表) …只有开启了动态选择条件功能的表,才可以在LDB数据库程序中对表进行动态选择条件处理。下面是数据库程序中如何使用动态选择条件示例:

    image056

    上面LDB数据库程序中的RSDS_WHERE条件内表来自RSDS类型组,相应源码如下:

    image057

    另外,上面LDB数据库程序中要能从DYN_SEL-CLAUSES内表读取数据,则必须在LDB选择屏幕里开启相应节点的动态选择条件:

    image058

    其中,DYN_SEL-CLAUSES内表行结构如下:

    image059

    6.3.3.1.            DYN_SEL

    PUT_<node> Form中的SELECT语句中Where从句如果要使用 DYNAMIC SELECTIONS 动态选择条件时,需要用到变量DYN_SEL,该数据对象是在LDB数据库程序中自动生成的,其类型如下(注:不必在LDB程序中加入下面代码行就可以直接使用DYN_SEL):

    TYPE-POOLS RSDS.
    DATA DYN_SEL TYPE RSDS_TYPE.

    你不必在程序中定义它就可以直接使用,但它只能在LDB数据库程序中使用,而不能用在报表程序中RSDS_TYPE数据类型是在类型组RSDS中定义的:

    TYPE-POOL RSDS .
    TYPES: RSDS_WHERE_TAB LIKE RSDSWHERE OCCURS 5."RSDSWHERE 类型为C(72)
    TYPES: BEGIN OF RSDS_WHERE,
             TABLENAME
    LIKE RSDSTABS-PRIM_TAB,
             WHERE_TAB
    TYPE RSDS_WHERE_TAB,
          
    END OF RSDS_WHERE.
    TYPES
    : RSDS_TWHERE TYPE RSDS_WHERE OCCURS 5.

    TYPES: BEGIN OF RSDS_TYPE,
            
    CLAUSES TYPE RSDS_TWHERE,
             TEXPR  
    TYPE RSDS_TEXPR,

            
    TRANGE  TYPE RSDS_TRANGE,
          
    END   OF RSDS_TYPE.

    RSDS_TYPE是一个深层结构的结构体,里面三个字段都是内表类型,其中以下两个字段重要:

    6.3.3.1.1.     RSDS_TYPE-CLAUSES

    Where从句部分,实则存储了可直接用在WHERE从句中的动态Where条件内表,可以在Where动态语句中直接使用,该组件为内表,存储了用户在选择屏幕上选择的LDB动态选择字段

     

    每个被选择的LDB屏幕动态选择字段都会形成一个条件,并存储到RSDS_TYPE-CLAUSES-WHERE_TAB内表中,WHERE_TAB内表中存储的就是直接可以用在Where从句中的动态选择条件中

     

    每个表(节点)都会有自己的CLAUSES-WHERE_TAB动态条件内表,这是通过CLAUSES-TABLENAME区别的

     

    现假设有名为 ZHK LDBSCARR为该LDB的根节点,且仅有SPFLI一个子节点。LDB选择屏幕 Include文件DBZHKSEL内容如下:

    SELECT-OPTIONS S_CARRID FOR SCARR-CARRID.
    SELECT-OPTIONS S_CONNID FOR SPFLI-CONNID.

    "需要先开始动态选择条件功能
    SELECTION-SCREEN DYNAMIC SELECTIONS FOR TABLE SCARR.

    LDB数据库程序SAPDBZHK中,PUT_SCARR过程中使用dynamic selection的过程如下:

    FORM PUT_SCARR.
     
    STATICS: DYNAMIC_SELECTIONS TYPE RSDS_WHERE,FLAG_READ. "定义成静态类型的是防止再次进入此Form时,再次初始化DYNAMIC_SELECTIONS结构,即只执行一次初始化代码
      IF FLAG_READ = SPACE.
        DYNAMIC_SELECTIONS
    -TABLENAME = 'SCARR'.
       
    READ TABLE DYN_SEL-CLAUSES WITH KEY DYNAMIC_SELECTIONS-TABLENAME INTO DYNAMIC_SELECTIONS.
        FLAG_READ
    = 'X'.
     
    ENDIF.
     
    SELECT * FROM
    SCARR  WHERE CARRID IN S_CARRID AND (DYNAMIC_SELECTIONS-WHERE_TAB). "使用动态Where条件
       
    PUT SCARR.
     
    ENDSELECT
    .
    ENDFORM.

    6.3.3.1.2.     RSDS_TYPE-TRANGE

    该字段是一个内表,存储了CLAUSES的原数据,CLAUSES内表里的数据实质就是来源于TRANGE内表,只是CLAUSES已经将每个表字段的条件拼接成了一个或多个条件串了(形如:“XXX字段 = XXX条件”),但是TRANGE内表与RANGES tables相同,存储的是字段最原始的条件值,使用时,在WHERE从句中使用 IN 关键字来使用这些条件值(这与SELECT-OPTIONS类型的屏幕参数用户是完全一样的)。

    但是,使用TRANGE没有直接使用CLAUSES灵活,因为使用TRANGE时,WHERE从句里的条件表字段需要事先写好,这实质上不是动态条件了,可以参考以下实例,与上面CLAUSES用法相比就更清楚了:现修改上面的示例:

    SELECT-OPTIONS S_CARRID FOR SCARR-CARRID.
    SELECT-OPTIONS S_CONNID FOR SPFLI-CONNID.

    "需要先开始动态选择条件功能
    SELECTION-SCREEN DYNAMIC SELECTIONS FOR TABLE SCARR.

    LDB数据库程序SAPDBZHK中,PUT_SCARR过程中使用dynamic selection的过程如下:

    FORM PUT_SCARR.
      STATICS: DYNAMIC_RANGES TYPE RSDS_RANGE, "存储某个表的所有屏幕字段的Ranges
              
    DYNAMIC_RANGE1 TYPE RSDS_FRANGE,"存储某个屏幕字段的Ranges
             
    DYNAMIC_RANGE2 TYPE RSDS_FRANGE,
              FLAG_READ."确保DYN_SEL只读取一次
     
    IF FLAG_READ = SPACE.
        DYNAMIC_RANGES
    -TABLENAME = 'SCARR'
    .
        "先取出 SCARR 表的所有屏幕字段的Ranges
       
    READ TABLE DYN_SEL-TRANGE WITH KEY DYNAMIC_RANGES-TABLENAME                              INTO DYNAMIC_RANGES.
        "再读取出属于某个字段的Ranges
        DYNAMIC_RANGE1
    -FIELDNAME = 'CARRNAME'.
       
    READ TABLE DYNAMIC_RANGES-FRANGE_T WITH KEY DYNAMIC_RANGE1-FIELDNAME
                                 
    INTO DYNAMIC_RANGE1.

        DYNAMIC_RANGE2
    -FIELDNAME = 'CURRCODE'.
       
    READ TABLE DYNAMIC_RANGES-FRANGE_T WITH KEY DYNAMIC_RANGE2-FIELDNAME
                                 
    INTO DYNAMIC_RANGE2.

        FLAG_READ
    = 'X'.
     
    ENDIF.
     
    SELECT * FROM SCARR
       
    WHERE CARRID IN
    S_CARRID
       
    AND
    CARRNAME IN DYNAMIC_RANGE1-SELOPT_T"使用IN 关键字使用Ranges内表
       
    AND CURRCODE IN DYNAMIC_RANGE2-SELOPT_T."(与select-options屏幕参数是一样的用法)
       
    PUT SCARR.
     
    ENDSELECT
    .
    ENDFORM.

    6.3.4.   FIELD SELECTION动态选择字段

    SELECTION-SCREEN FIELD SELECTION FOR NODE|TABLE <node>.语句的作用是开启节点<node>的动态字段选择的功能(形如:SELECT (选择字段内表) FROM…,而不是SELECT * FROM …即选择了哪些字段,就只查询哪些字段,而不是将所有字段查询出来,进而可以提高性能)

    在可执行报表程序里,可以通过GET node [FIELDS f1 f2 ...] 语句中的 FIELDS选项来指定要读取字段;

    image060

    另外,上面LDB数据库程序中要能从SELECT_FIELDS内表读取数据,则必须在LDB选择屏幕里开启相应节点的动态选择字段:

    image061

    其中,SELECT_FIELDS内表行结构如下:

    image062

    image063

    6.3.4.1.            SELECT_FIELDS

    PUT_<node> Form中的SELECT语句中Where从句如果要使用 FIELD SELECTION 动态选择字段时,需要用到数据对象SELECT_FIELDS,在LDB数据库程序中,通过从SELECT_FIELDS内表中就可以读取GET node [FIELDS f1 f2 ...] 语句传递进来的选择字段,SELECT_FIELDSLDB数据库程序自动生成的,其类型如下(不必在LDB程序中加入下面代码行,直接就可以使用SELECT_FIELDS内表,另外在相连的报表程序中也可以使用,这与DYN_SEL不同):

    TYPE-POOLS RSFS.
    DATA SELECT_FIELDS
    TYPE RSFS_FIELDS.

    image064

    RSDS_FIELDS中的FIELDS里存储的就是GET…FIELDS…语句传递过来的用户指定的查询字段,FIELDS内表可以直接使用在 SELECT…从句中。

     

    现假设有名为 ZHK LDBSCARR为该LDB的根节点,且仅有SPFLI一个子节点。LDB选择屏幕 Include文件 DBZHKSEL内容如下:

    SELECT-OPTIONS S_CARRID FOR SCARR-CARRID.
    SELECT-OPTIONS S_CONNID FOR SPFLI-CONNID
    .
    "需要先开始动态选择字段功能
    SELECTION-SCREEN FIELD SELECTION FOR TABLE SPFLI.

     

    LDB数据库程序SAPDBZHK中,PUT_SCARR过程中使用dynamic selection的过程如下:

    FORM PUT_SPFLI.
     
    STATICS: FIELDLISTS TYPE RSFS_TAB_FIELDS,
               FLAG_READ
    ."确保SELECT_FIELDS只读取一次
     
    IF FLAG_READ = SPACE.
        FIELDLISTS
    -TABLENAME = 'SPFLI'
    .
        "读取相应表的动态选择字段
       
    READ TABLE SELECT_FIELDS WITH KEY FIELDLISTS-TABLENAME INTO FIELDLISTS.
        FLAG_READ
    = 'X'.
     
    ENDIF.
      SELECT (FIELDLISTS-FIELDS)"动态选择字段
             
    INTO CORRESPONDING FIELDS OF SPFLI FROM SPFLI
             
    WHERE CARRID = SCARR-CARRID AND CONNID IN S_CONNID.

       
    PUT SPFLI.
     
    ENDSELECT
    .
    ENDFORM.

    在相应的可执行报表程序里,相应的代码可能会是这样的:

    TABLES SPFLI.
    GET SPFLI FIELDS
    CITYFROM CITYTO.
        ...

    GET语句中的FIELDS选项指定了除主键外需要查询来的字段,主键不管是否选择都会被从数据库表中读取出来,可以由下面报表程序中的代码来证明

    DATA: ITAB LIKE SELECT_FIELDS,
          ITAB_L
    LIKE LINE OF ITAB,
          JTAB
    LIKE ITAB_L-FIELDS,
          JTAB_L
    LIKE LINE OF JTAB.
    START-OF-SELECTION.
      ITAB
    = SELECT_FIELDS. "在报表程序中也可以直接使用LDB程序中的全局变量!
     
    LOOP AT ITAB INTO ITAB_L.
       
    IF ITAB_L-TABLENAME = 'SPFLI'.
          JTAB
    = ITAB_L-FIELDS.
         
    LOOP AT JTAB INTO JTAB_L.
           
    WRITE / JTAB_L.
         
    ENDLOOP.
       
    ENDIF.
     
    ENDLOOP.

    如果报表程序中的GET语句是这样的:GET SPFLI FIELDS CITYFROM CITYTO.,则输入结果为:

    CITYTO

    CITYFROM

    MANDT

    CARRID

    CONNID

    可以从输出结果看出,主键MANDTCARRIDCONNID会自动的加入到SELECT_FIELDS内表中,一并会从数据库中读取出来

    6.4.  数据库程序中重要FORM

    ? FORM INIT

    在选择屏幕处理前仅调用一次(在PBO之前调用)

    ? FORM PBO

    在选择屏幕每次显示之前调用,即LDB选择屏幕的PBO事件块

    ? FORM PAI

    用户在选择屏幕上输入之后调用,即LDB选择屏幕的PAI事件块(之后?)。

    FORM带两个接口参数FNAME and MARK将会传到subroutine 中。FNAME存储了选择屏幕中用户所选择SELECT-OPTIONPARAMETERS屏幕字段名MARK标示了用户选择的是单值还是多值条件:MARK = SPACE意味着用户输入了一个简单单值或者范围取值,MARK = '*'意味着用户在Multiple Selection screen 的输入(即多个条件值)FNAME = '*' MARK = 'ANY'表示所有的屏幕参数都已检验完成,即可以对屏幕整体参数做一个整体的检测了(这里的意思应该就是相当于AT SELECTION-SCREEN)。

    ? FORM PUT_<node>

    最顶层节点<node>所对应的FORM PUT_<node>会在START-OF-SELECTION事件结束后自动被调用,而其他下层节点所对应的FORM会由它的上层节点所对应的FORM中的PUT <node>语句来触发(在上层节点所对应的可执行程序中的相应GET事件块执行之后触发)

    PUT <node>.

    此语句用是PUT_<node>子过程中的特定语句,它是与PUT_<node> Form一起使用的,通常是放在循环处理数据循环过程中。PUT语句根据LDB的结构指引了报表程序的逻辑。该语句会触发相应的报表程序的GET <node>事件。当GET事件块执行完后,如果有下层节点,则还会调用下层节点所对应的FORM PUT_<node>

    PUT语句是该FormPUT_<node>)中最主要的语句:此语句仅仅只能在LDB数据库程序的Form中使用。

    PUT_<node>调用结束后,报表程序中相应GET <node> LATE事件块也会自动调用。

     

    首先,根节点所对应的PUT_<root>会自动执行,此Form中的PUT <node>会以下面的先后顺序来执行程序:

    1.      如果LDB数据库程序包含了AUTHORITY_CHECK_<table>语句,则PUT语句的第一件事就是调用它

    2.      然后,PUT语句会触发报表程序相应的GET事件

    3.      再后,PUT语句会去调用LDB程序中下一节点的PUT_<node>子过程(此过程又会按照这里的三步来运行),直到下层所有子孙节点PUT_<node>过程处理完成(深度遍历),才会回到最上一层节点的PUT语句

    4.      当控制权从下层节点的PUT_<node>返回时,PUT语句还会触发当前节点的GET <node> LATE报表事件

    image065

    GET事件块会在LDB程序从数据库表中读取到一行数据时被触发

    6.5.  LDB选择屏幕:静()态选择屏幕、动态选择视图

    image066

    image067

    image068 image069

    在报表选择屏幕上是否显示LDB普通选择条件(即静态的,与动态选择条件相对应),则要看报表程序中是否使用了对应的 TABLE <node>语句,如果有,则与<node>节点相关的所有LDB选择条件都会显示在报表程序的选择屏幕上,如果没有此语句,则与<node>节点相关的所有LDB选择条件都会不会显示(但如果某个节点没有在TABLE语句中进行定义,但其子节点,或子孙节点在TABLE语句中进行了定义,则这些子孙节点所对应的父节点所对应LDB屏幕选择条件还是会嵌入到报表选择屏幕中)。有几种情况:

    l  如果报表程序中只有根节点的定义语句:

    image070

    则报表程序的选择屏幕只会将spfli节点相关的普通选择条件内嵌进来,子孙节点不会显示出来:

    image071

    l  如果报表程序只有子孙节点定义语句:

    image072

    则报表程序的选择屏幕中,会将sbook的父节点SFLIGHT以及爷节点SPFLI相关的LDB静态选择内嵌进来

    image073

    如果LDB的选择屏幕在没有创建选择视图的情况下:动态选择是否显示在报表程序的选择屏幕中,首先要看报表程序中是否使用了 TABLE <node>对需要动态显示的节点进行了定义(如果这个节点是上层节点,则此节点为本身也可以不在TABLE语句定义,而是对其子孙节点进行定义也是可以的),再者,还需要相应的<node>节点在LDB屏幕选择Include程序中的SELECTION-SCREEN DYNAMIC SELECTIONS FOR TABLE <node>语句中进行定义,注:要显示,则对应节点一定要在此语句中定义过,而不是像报表程序中的节点只对其子孙节点进行定义即可,而是谁需要动态显示,则谁就得要在动态定义语句中进行定义,如下面在LDB选择屏幕Include程序中只对SBOOK的上层节点SPFLI,SFLIGHT进行了定义,并没有对SBOOK进行定义:

    image074

    而在报表程序中只能SBOOK进行了定义:

    image075

    但最后在报表动态选择屏幕中,只有SPFLI,SFLIGHT两个表的条件(需使用SELECTION-SCREEN DYNAMIC SELECTIONS语句对SPFLI,SFLIGHT节点进行定义),而SBOOK并没有:

    image076

    在没有创建选择视图的情况下,以表名来建小分类,且动态条件字段为整个表的所有字段

     

    如果LDB的选择屏幕在有选择视图的情况下:只要存在选择视图,则只显示选择视图里被选择的字段,其他任何字段一概不显示。下面只将SPFLI-CARRIDSFLIGHT-CONNID两个字段已分别纳入到了0102分组中,而SBOOK节点中没有字段纳入:

    image077

    image078

    报表程序里将SBOOK节点定义在了TABLES语句中,所以,从SBOOK这一级开始(包括)向上所有节点的所对应的字段,如果纳入了选择视图中,则选择屏幕显示如下:

    image079

  • 相关阅读:
    深度学习方面的学术交流平台?
    如何用简单例子讲解 Q
    强化学习之Q-learning简介
    学完了在线课程?如何开启深度学习论文的阅读模式
    Java高级特性之枚举
    uboot启动流程
    Chromium网页Layer Tree创建过程分析
    Sql控制反转小尝试
    模拟日历计算 poj1008
    安卓零碎知识集中
  • 原文地址:https://www.cnblogs.com/jiangzhengjun/p/4264712.html
Copyright © 2011-2022 走看看