[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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM