从数据库中取数据有三种方式:OPEN SQL NATIVE SQL和LOGICAL DATABASE,LOGICAL DATABASE相对于前两种方式,有下列优势:
l 它是按照primary key sequence来取数据的
l 可以在logic database program加入权限检查
l 可以自动产生selection screen使查询更加灵活
l 程序员不需要知道logical database中表之间的具体关系
l 对于logical database的性能优化可以影响到使用它的任何程序
l 维护和增强可以实现中央处理
4.6C中SAP提供了大约190个logical database。如果logical database有三个字符,前两个是logical database的名字第三个是logical database的application area。看每个字符代表的那个application area可以通过程序的attribute的application field的F4来查看。只有executable或report可以使用logical database。关键字NODE <node>,决定了logical database中的那个node要被使用,NODES为这个node准备响应的存储空间(work area或table area由node type来决定)。在4.6中tables仍然可以被使用。当logical database从数据库中读取数据时就会执行PUT <node>从而触发GET事件,GET <node>并不取数据。事件的执行顺序是由logical database本身的结构决定的。在get event中使用fields很很重要就像OPEN SQL中尽量避免SELECT *一样。Logical database是由很多subobjects组成的,structure决定了hierarchy以及数据的读取顺序。Node name最多有14个字符组成,有四种Node type:
l Table(type T):node name是一个transparent table name,node name和table name的名称必须一致,不允许deep types。
l DDIC type(type S):任何Node name都可以,node type由dictionary中的structure或table type来决定,允许deep types。
l Type groups(type C):node type是在type group中定义,type group name必须在Type group field中维护。应当优先使用DDIC TYPE以便像SAP QUERY这样的应用也可以使用。
l Dynamic nodes(type A):没有固定的type,它在程序运行时才能够确定。
报表的START-OF-SELECTION在所有的get events之前发生,END-OF-SELECTION在所有的get events之后发生。GET <node> events一旦从logical database中取得数据时都回触发,所以这个事件会被多次触发。Get events的执行顺序由logical database的结构决定。当节点的所有子节点都被处理后再节点的下一个数据被处理之前就会触发GET <node> LATE事件,在事件开始系统会自动创建一line feed,并把color,font和intensity设为系统默认,如果在其他事件中设置了color,也会被重设为系统默认。CHECK结束当前事件,STOP结束程序处理执行END-OF-SELECTION,在END-OF-SELECTION中的STOP,则之际显示list buffer。EXIT结束程序处理,也不执行END-OF-SELECTION,直接显示list buffer中的内容。
还可以使用REJECT,当前的处理被终止,还可以在下一次数据读取时触发。Logical database程序有一个include:db<name>sel,这里定义了logical database的selection screen。For node把selection分配给单个的logical node。Selection screen的屏幕形式由程序中的nodes表达式决定。Field selection可以由Logical database程序中的node决定,这个通过SELECTION-SCREEN中的FIELD SELECTION FOR NODE决定。Logical database程序中的这段代码可以使application program中通过GET <node> FIELD <field list>来限制取出数据的数量,logical database程序中可以为某个Node设置dynamic selection,在语句中可以通过addition:DYNAMIC SELECTIONS FOR NODE来实现,这样Dynamic selection button就会在你的报表的selection screen中出现。另外logical database还可以定义不同的selection screen version。如果你在报表程序中指定了一个logical database,你就可以使用logical database的selection screen了。如果在report程序中你只指定了logical database的子节点,其上层的节点的筛选条件也可以被使用。对于T(table)类型的node,可以通过TABLES来声明它的work area。值得注意的是logical database总是按照自己的结构来读取数据的,所以当你需要读取logical database的比较深层次的node的数据的时候,你需要考虑换一个其所在层次比较高的logical database或者自己写取数逻辑。Selection view决定了什么样的字段会显示在selection screen。可以创建类型为CUS的自己的view,或者覆盖类型为SAP的view。
Logical database程序的命名规则是:SAPDB<ldbname>其中ldbname是logical database的名称。这些程序是由subroutine组成的,每个subroutine对应于一个事件。例如subroutine <init>是在logical database程序启动前执行,用来初始化变量和屏幕选择。还有其他的一些subroutine也是在屏幕的PBO或PAI事件中发生的。例如AUTHORITY CHECK是在PAI中发生的。数据库访问是在put_<node> subroutine中实现的。这个subroutine可能会被多次执行,这取决于屏幕的选择条件。这些subroutine的执行顺序由logical database的structure来决定。使用logical database的report在执行时控制权首先属于logical database program。每个事件在logical database program中都有一个对应的subroutine。在LDB和相应的report之间交互的时候LDB中的subroutine都会先执行。Logical database program读取数据的顺序是按照其structure执行的,总是从最顶部向下循环。LDB program是通过PUT_<NODE> subroutine来访问数据的,在PUT event中,control由LDB program传向report program的GET EVENT。取出来的数据或放到report program相应的work area中。GET event一旦执行完毕control就会还给LDB program。Data read的depth是由report program的GET event来决定的。如果node的某个field没有筛选条件,可以在report program中增加这个字段select-options在这个node的GET event中通过check来筛选。
2009-6-19
Open sql完全集成与ABAP WORKBENCH中,R/3 SYSTEM可以通过buffer来提高性能。NATIVE SQL通过下面的方式来实现:
| |||
| |||
| |||
禁止使用NATIVE SQL去改变数据,如果不得不使用native sql应当将他们放在独立的include中以便维护。
实现多表查询的四种方式:
l Database view in the ABAP dictionary database view可以使用缓存提高性能,它的主要优点是统一维护,所有的用户都可以使用,程序中的select语句比较简单。缺点是不够灵活。
l INNER JOIN OUTER JOIN join fields不局限于key fields。可以使用外键字段或者具有相同domain的字段。Join是从数据库中取数据的一种高效方式,先取那个表以及使用那个index都是数据库自己决定的。使用LEFT OUTER JOIN时,右边表不存在的记录会用null填充,但是在ABAP将会赋给相应类型的初始值。Left outer join的局限性,在left outer join右边只能有一个表,不能再有额外的join。在on condition中只能使用AND。ON CONDITION中的每个comparison必须有一个右边表的字段。如果from clause中有一个outer join,
l FOR ALL ENTRIES(ARRAY FETCH)使用ARRAY FETCH时,应当通过检查SY-SUBR来确保每一个SELECT语句都能取得数据。SELECT...FOR ALL ENTRIES IN <ita>相当于对<itab>中的每条记录做了个or condition。需要注意的是这里where carrid = itab_spfli-carrid中的itab_spfli-carrid只是一个placeholder,并不是internal table中的一个component。Internal table中的duplicates是不允许的。理论上,internal table中可以有任意多条记录。Array fetch与join和database view相近,但一般情况下后者的性能要远远优于前者。
l Nested select statements
l 4.0之后还可以使用sub query.。参考:http://help.sap.com/saphelp_nw04/helpdata/en/60/515f3eca2a11d2a97100a0c9449261/frameset.htm
提高多表查询性能的几条原则:
l 取尽量少的数据 在所有select表达式中都要通过where来限制数据。对于需要accumulating数据的情况,如果能通过SQL AGGREGATE功能(比如:MIN,MAX,AVG,SUM和COUNT(*)等)实现就不要在程序中编写代码实现。使用DISTINCT而避免在程序中通过array fetch,sort,delete adjacent duplicates来实现。合适的时候可以通过subquery或having。任何情况下都要把filter和summation交给database引擎来处理而避免在程序中处理。
l 保证database server和application server之间的数据传递是最小的。报表程序中应尽量避免使用select *。而应当使用field list,并保证其在程序中的顺序与ABAP DICTIONARY中的顺序一致。
l 不要使用MOVE-CORRESPONDING给变量赋值
l 减少数据库的请求次数,尽量避免使用nested select
l 使用where条件时,尽量匹配已有的index,通过SQL TRACE可以检查程序中的SQL语句。所有的on condition中必须有一个真正的condition(即在condition中一个字段来自于左边的表一个字段来自于右边的表)。