zoukankan      html  css  js  c++  java
  • ABAP 语言特色

    CD263
    ABAP语言新特点
    What is new in ABAP in NW 7.0, EhP2?
    Jean Guo
    Zhong Ba
    Tao Xu
    ©2010 SAP AG. All rights reserved. / Page 2
    Disclaimer
    This presentation outlines our general product direction and should not be relied on in making a 
    purchase decision. This presentation is not subject to your license agreement or any other 
    agreement with SAP. SAP has no obligation to pursue any course of business outlined in this 
    presentation or to develop or release any functionality mentioned in this presentation. This 
    presentation and SAP's strategy and possible future developments are subject to change and 
    may be changed by SAP at any time for any reason without notice. This document is provided 
    without a warranty of any kind, either express or implied, including but not limited to, the implied  
    warranties of merchantability, fitness for a particular purpose, or non-infringement. SAP 
    assumes no responsibility for errors or omissions in this document, except if such damages 
    were caused by SAP intentionally or grossly negligent.
    ©2010 SAP AG. All rights reserved. / Page 3
    课程安排
    1. 表达式
    2. 内表
    3. 基于类的异常处理
    4. 十进制浮点数
    5. 使用Locator和数据流读写数据库
    6. Boxed 组件
    ©2010 SAP AG. All rights reserved. / Page 4
    运算表达式只能由COMPUTE命令完成
    算术表达式(数字计算)
    二进制表达式(位计算)
    控制逻辑中只能使用纯逻辑表达式
    表达式–现状
    tmp1= n / i.
    tmp2= ME->meth( tmp1 ) * i.
    IF tmp2= n.
    EXIT.
    ENDIF.
    过多的辅助变量给编程造成困难
    一些内建方法(如strlen, lines)只能使用在非常特定的操作数位置,用途
    很有限
    ©2010 SAP AG. All rights reserved. / Page 5
    新的运算表达式类型:字符串表达式
    支持运算表达式的地方:
    逻辑表达式当中
    IMPORTING参数中
    ABAP语句中各种类型的操作数位置
    扩展之后的表达式–主要功能
    在方法调用时允许嵌套及链式调用
    扩展内建方法集(如字符串处理内建方法)
    通过内建方法的调用使编程更加紧凑高效
    IF ME->meth( n / i ) * i = n.
    EXIT.
    ENDIF.
    运算表达式作为方法实参
    运算表达式作为逻辑表达式一个
    操作数
    ©2010 SAP AG. All rights reserved. / Page 6
    在逻辑表达式中使用计算表达式
    CHECK sy-index > i + 1.
    WHILE x1 BIT-AND x2 BYTE-CO
    xs1 BIT-OR xs2. 位运算
    LOOP AT tab INTO wa
    WHERE c BETWEEN n – 10 AND n + 10.
    在比较语句中的运算
    IF sy-tabix MOD 10 = 0.
    ULINE.
    ENDIF.
    算术运算
    IF int / ( 4 * int ) = 0. 整型运算→ true
    IF flt / ( 4 * flt ) = 0. 浮点型运算→ false
    ©2010 SAP AG. All rights reserved. / Page 7
    在IMPORTING参数中使用运算表达式
    o->m( abs( i * 2 ) + 1 ).
    不指定参数名
    cl=>m( p1 = i + 1  p2 = 2 ** j ).
    指定参数名
    o->m( pX10  = BIT-NOT x1 
    pXStr = x1 BIT-OR x2 ).
    任意二进制类型参数均接受二进制运算表达
    式
    cl=>m( pInt = 12 / 10 
    pDec = 12 / 10 ).
    任意数字类型的参数均接受算术运算表达式
    形参的类型决定运算类型(pInt1, pDec
    1.2)
    CREATE OBJECT o EXPORTING p = i + 1 .
    调用构造函数构建实例时的
    参数
    RAISE EXCEPTION TYPE lcx
    EXPORTING p = i + 1 .
    实例化异常时的参数
    o->m( cl=>m( p1 = o->i~m( 7 ) ) ).
    将方法调用作为参数
    ©2010 SAP AG. All rights reserved. / Page 8
    其他ABAP语句中的运算表达式(输入操作数)
    READ TABLE itab
    INDEX lines( itab ) …
    APPEND LINES OF oref->tab( )
    FROM i + 1 TO n – 1 TO t.
    DO strlen( txt ) – 1 TIMES.
    数字类型的输入操作数
    MOVE-CORRESPONDING o->struct( ) TO x.
    在使用通用类型输入操作数的
    位置使用方法调用
    也可用于WAIT,SET BIT,GET BIT,SHIFT,FIND,REPLACE,… 
    也可用于其他使用内表操作索引的语句如LOOP,INSERT,DELETE,…
    也可用于其他使用通用类型输入操作数的语句(主要是字符类型操作语句)如
    CLEAR, FIND, REPLACE,…
    也可用于其他使用工作区/表的内表操作语句如LOOP, INSERT, DELETE, 
    READ, MODIFY,…
    ©2010 SAP AG. All rights reserved. / Page 9
    链式方法调用
    cl=>get_instance( )->cleanup( ).
    链式方法调用
    IF oref->m1( )->intf~m2( )->a > 1.
    以链式调用访问实例的成员变
    量
    CASE cl=>m1( )->obj->m2( ) .
    以链式调用访问实例的成员方
    法
    ©2010 SAP AG. All rights reserved. / Page 10
    扩展之后的表达式应用–不足
    lcl=>cm_ii( 1 + abs(
    lcl=>factory2(
    f_in1 = lcl=>factory0( )->m_lif( )->im_lif( )->im_ii( i )
    f_in2 = lcl=>cm_ii( 2 ** i ) - 3
    )->m_ii(
    lcl=>factory1( f_in = j + 4
    )->m_lif_i(
    lcl=>cm_ii( 5 )
    )->im_ii( 6 )
    ) ) ).
    ©2010 SAP AG. All rights reserved. / Page 11
    扩展之后的表达式应用–不足
    不支持编译器优化,如
    公共子表达式消去
    循环不变式提取
    编程人员应合理使用中间变量以使程序更清晰
    ABAP变得容易混淆
    但ABAP调试器可以支持复杂表达式
    可以显示方法返回值
    可以显示中间运算结果
    px_width=px_width+
    col->get_layout()->width * 
    units->to_px_width(col->get_layout()->width_unit).
    ©2010 SAP AG. All rights reserved. / Page 12
    字符串表达式
    新的运算表达式: 字符串表达式
     串连 txt1 && txt2
     字符串模板 |…Text…{ expression format = …}…Text…|
    字符串表达式
     用于方便地创建格式化的文本(如xml)
     同算术表达式和二进制表达式一样可以用于很多位置
     可用于替换大量的:
    WRITE TO语句及相应的辅助变量
    CONCATENATE语句
    新的内建方法
     用于字符串处理:23个
     用于非字符串处理:8个
     用于字符串断言:4个
    ©2010 SAP AG. All rights reserved. / Page 13
    DATA txt TYPE string.
    CONCATENATE txt1 txt2 
    INTO txt.
    CONDENSE txt.
    txt = condense( txt1 && txt2 ).
    字符串连接
    连接操作符
    txt1 && txt2
    替换CONCATENATE语句以及相应的辅助变量
    ©2010 SAP AG. All rights reserved. / Page 14
    字符串模板
    字符串模板能够将表达式与文本字符结合起来
    |…Text…{expression format = …}…Text…|
    文本字符 内嵌表达式 格式选项 文本字符
    do 20 times.
    prog1 = |REP{ sy-index - 1 }TEST|.
    prog2 = |/{ nspace }/REP{ sy-index - 1 zero = no }TEST|.
    prog3 = |/{ nspace }/REP{ sy-index - 1 align = right
    pad = '0'
    width = 2 }TEST|.
    enddo. 
    字符串模板以| 作为开始和结束
    ©2010 SAP AG. All rights reserved. / Page 15
    字符串模板的特点
    字符串模板
     允许将动态及静态文本相结合
     可使用字符转换,格式化以及字符串连接
     支持控制字符(如“\n” 可以新起一行)
     不能跨越多行(需要使用„&‟ 来连接多行)
     可用于替换WRITE TO 语句及辅助变量
     对于技术性文本(如code/xml/html) 进行了优化
     不支持语言相关的模板
    s = |Hello, \n| &
    |today is { sy-datum date = iso } \n| &
    |now is { sy-uzeit time = iso }|.
    ©2010 SAP AG. All rights reserved. / Page 16
    字符串模板中的内嵌表达式
    内嵌表达式
     以„{„ 和„}‟ 作为开始和结束
     表达式结果会被转换为字符串
     格式选项可用于定义字符串格式
     在内嵌表达式中使用的换行没有意义
    s = |<line index=“{ sy-tabix }” | &
    |kind=“{ o->get_kind( ) }”>|.
    s = |timestamp=“{ sy-datum date = iso }T| &
    |{ sy-uzeit time = iso }”|.
    格式选项
    ©2010 SAP AG. All rights reserved. / Page 17
    常用格式选项
    可用于所有类型
    width [integer number] 总输出宽度
    align {left|right|center} 对齐方式(默认为左对齐)
    pad [character] 填充字符
    case {raw|upper|lower} 大小写
    ©2010 SAP AG. All rights reserved. / Page 18
    可用于数字类型的格式选项
    可用于数字类型
    sign
    {left|leftplus|leftspace|
    right|rightplus|rightspace}
    正负号位置(默认左侧)
    exponent [integer number] 指数
    decimals [integer number] 小数位数
    zero {yes|no} 消零处理
    number  {raw|user|environment} 小数格式(默认raw)
    style CL_ABAP_FORMAT中的常量 浮点数格式
    currency 数据库表TCURC中的值 货币代码
    ©2010 SAP AG. All rights reserved. / Page 19
    可用于日期时间类型的格式选项
    可用于日期和时间
    date
    raw (“20080906”)
    user 使用自定义设置
    iso (“2008-09-06”)
    environment  使用区域设置
    日期格式
    (默认为raw)
    time
    raw “182504”
    user 使用自定义设置
    iso “18:25:04”
    environment 使用区域设置
    时间格式
    (默认为raw)
    timestamp
    space 日期时间
    user 使用自定义设置
    iso 日期„T‟ 时间
    environment 使用区域设置
    时间戳格式
    timezone 数据库表TTZZ-TZONE中的值 时区
    ©2010 SAP AG. All rights reserved. / Page 20
    7.0 EhP2之前的字符串处理
    ABAP命令集, 如:
     CONCATENATE
     SPLIT
     CONDENSE
     FIND SUBSTRING | REGEX
     REPLACE SUBSTRING | REGEX
    逻辑操作符集, 如:
     CS, NS
     CA, NA 
     CP, NP
    内建方法集, 如:
     strlen( ... )
     charlen( ... )
    字符串子串操作:
     ... text+off(len) ...
    ©2010 SAP AG. All rights reserved. / Page 21
    字符串操作可在表达式中直接使用
    新的字符串操作内建方法
    text= 'Product description: Superdooper smartphone'.
    desc= to_upper( condense(
    substring_after( val = textsub = `description:`
    occ = 1 len = 18 ) ) ).
    text= `... use product no. &prod-id& (&prod-desc&).`.
    LOOPAT replacementsASSIGNING <repl>.
    text = replace( val = text
    sub = '&' && <repl>-repl && '&'
    with = <repl>-content ).
    ENDLOOP. 
    结果:"SUPERDOOPER SMART" 
    结果:"... use product no. XY007 (SUPERDOOPER SMART)." 
    'prod-id‘ `XY007`
    'prod-desc‘ desc
    参数替换= 
    ©2010 SAP AG. All rights reserved. / Page 22
    返回值为字符串的方法(1)
    提取子串
    substring( val = s [off = i1] [len = i2] )
    substring_after( val = s (sub|regex) = s1 [occ = i1] [len = i2] )
    substring_from( val = s (sub|regex) = s1 [occ = i1] [len = i2] )
    substring_before( val = s (sub|regex) = s1 [occ = i1] [len = i2] )
    substring_to( val = s (sub|regex) = s1 [occ = i1] [len = i2] )
    segment( val = s index = i [sep = s1] )
    match( val = text regex = regex [case = case] [occ = occ] )
    字符串移位
    shift_left( [val =] s [places = i1 | circular = i2 | sub = s1] )
    shift_right( [val=] s [places = i1 | circular = i2 | sub = s1] )
    ©2010 SAP AG. All rights reserved. / Page 23
    返回值为字符串的方法(2)
    字符串转化
    replace( val = s (sub|regex) = s1 with = s2 [occ = i1] [case = c] )
    insert( val = s sub = s1 [off = i] )
    repeat( val = s occ = i )
    condense( [val =] s [del = s1] [from = s2] [to = c] )
    reverse( [val =] s )
    escape( val = s format = f )
    translate( val = s from = s1 to = s2 )
    to_upper([val =] s )
    to_lower([val =] s )
    to_mixed( [val =] s [sep = c1] [case = c2] [min = i] )
    from_mixed( [val =] s [sep = c1] [case = c2] [min = i] )
    ©2010 SAP AG. All rights reserved. / Page 24
    返回值为字符串的方法(3)
    oref->meth( 
    boolc( …condition… )  
    ).
    if …condition… .
    temp_flag = 'X'.
    else.
    temp_flag = ' '.
    endif. 
    oref->meth( temp_flag ).
    连接内表各行
    concat_lines_of( [table =] t [sep = s] ) 将内表<t> 各行以<s>为分隔符连接
    布尔运算
    boolc( logical-expression) 如逻辑表达式为真,返回„X‟ 否则返回„ ‟
    boolx( bit = i bool = logical-expression)
    返回值为一个Byte, 如果逻辑表达式结果为真,
    则此Byte第i位置1,否则置0
    ©2010 SAP AG. All rights reserved. / Page 25
    可在逻辑表达式中直接使用字符串内建方法
    新的用于字符串描述的内建方法
    IF not matches( val = email
    regex = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ).
    * Email format is not valid
    …
    如果email格式合法,则match方法返回真值
    text= `... use product no. XY007 (SUPERDOOPER SMART).`.
    IF find( val = text sub = 'XY'case= abap_true
    occ = 1
    off = 10 len = 20 ) <> -1.
    * Substring found
    …
    find方法给出子串’XY‘在text中从11位到31位的位移量
    如果找不到子串,则返回-1
    ©2010 SAP AG. All rights reserved. / Page 26
    字符串描述方法
    搜索子串(返回所找到位置的位移量)
    find( val= s (sub|regex) = s1 [off = i1] [len = i2] [occ= i3] [case = c] )
    find_end( val = s (sub|regex) = s1 [off = i1] [len = i2] [occ = i3] [case = c] )
    find_any_of( val= s sub = s1 [off = i1] [len = i2] [occ= i3] )
    find_any_not_of( val = s sub = s1 [off = i1] [len = i2] [occ = i3] )
    子串计数(返回所找到的子串数量)
    count( val = s (sub|regex) = s1 [off = i1] [len = i2] [occ = i3] [case = c] )
    count_any_of( val = s sub = s1 [off = i1] [len = i2] [occ = i3] )
    count_any_not_of( val = s sub = s1 [off = i1] [len = i2] [occ = i3] )
    字符串相似度(返回两个字符串的LevenshteinDistance值)
    distance( val1 = s1 val2 = s2 [max = i] )
    ©2010 SAP AG. All rights reserved. / Page 27
    字符串断言方法
    包含子串或字符
    contains( val = s (sub|start|end|regex) = s1 [off = i1] [len = i2] [occ = i3] [case = c] )
    contains_any_of( val = s (sub|start|end) = s1 [off = i1] [len = i2] [occ = i3])
    contains_any_not_of( val = s (sub|start|end) = s1 [off = i1] [len = i2] [occ = i3] )
    匹配正则表达式
    matches( val = text regex = regex [case = case] [off = off] [len = len] )
    ©2010 SAP AG. All rights reserved. / Page 28
    总结–扩展后的表达式
    扩展了表达式的用途
     支持了更多的操作数位置,特别是一些内表相关的ABAP语句
     与面向对象无缝集成(嵌套调用,链式调用)
    字符串表达式
     简单实用
     可以像算术表达式一样直观地使用
     丰富的格式选项
     丰富的内建方法
    想了解更多?
     运行ABAP report程序:DEMO_EXPRESSIONS
     查看ABAP在线文档
    Demo 演示& 练习
    ©2010 SAP AG. All rights reserved. / Page 30
    课程安排
    1. 表达式
    2. 内表
    3. 基于类的异常处理
    4. 十进制浮点数
    5. 使用Locator和数据流读写数据库
    6. Boxed 组件
    ©2010 SAP AG. All rights reserved. / Page 31
    为什么在内表中使用次键(Secondary Keys)?
    有键值的内表的优点(自4.0起支持) 
    对哈希表的键值快速访问,时间复杂度:O(1)
    Time
    Table Size
    Hashed
    ©2010 SAP AG. All rights reserved. / Page 32
    为什么在内表中使用次键(Secondary Keys)?
    有键值的内表的优点(自4.0起支持) 
    对哈希表的键值快速访问,时间复杂度:O(1)
    对排序表的键值快速访问,时间复杂度:O(log n)
    对排序表的部分连续快速处理(LOOP … WHERE 优
    化)
    Time
    Table Size
    Hashed
    Sorted
    ©2010 SAP AG. All rights reserved. / Page 33
    为什么在内表中使用次键(Secondary Keys)?
    有键值的内表的优点(自4.0起支持) 
    对哈希表的键值快速访问,时间复杂度:O(1)
    对排序表的键值快速访问,时间复杂度:O(log n)
    对排序表的部分连续快速处理(LOOP … WHERE 优
    化)
    非主键访问
    缓慢的性能,时间复杂度:O(n)
    可能会导致整体性能问题
    需要由手工实现的次键访问来进行性能优化,而
    这种手工实现很容易出错
    提供像数据库表一样的次键
    在添加次键的同时保留兼容性
    (不会自动隐式使用次键)
    编译器提示正确用法
    Time
    Table Size
    Hashed
    Sorted
    Standard
    实际应用中的低性
    能
    数据量小的情
    况下性能不错
    ©2010 SAP AG. All rights reserved. / Page 34
    内表的属性
    LH 0400 4.167              A380-800
    SQ 0866 1.625  A340-600
    UA 0007 2.572              767-200  
    CARRID CONNID DISTANCE      PLANETYPE
    行类型:
    t_flight
    主键
    QF 0005 1.000              747-400   索引访问
    4
    次键访问
    A340-600
    次键: 
    plane
    唯一性检查
    AA 0017 2.572          737-800
    主键访问
    UA 0007
    LH 0400 6.162              A340-600
    data flights type sorted table of t_flight
    with unique key carrid connid
    with non-unique sorted key plane components planetype.
    ©2010 SAP AG. All rights reserved. / Page 35
    定义次键
    次键是内表类型定义的一部分,即静态定义
    但在一些ABAP语句中(如READ, LOOP, …)次键以及组件可以动态指定
    次键定义必须完整, 也就是说如下属性必须全部指定
    定义次键名称(Keyname) , 系统保留字: PRIMARY_KEY,LOOP_KEY
    访问类型(Access kind): HASHED或SORTED
    唯一性(Uniqueness): UNIQUE或NON-UNIQUE,哈希值必须唯一(UNIQUE)
    组件(Key components): 可以使用自定义的组件列表或者使用TABLE_LINE
    最多支持15个次键
    DATA <Well-known table definition>
    WITH
    KEY 
    COMPONENTS
    <Uniqueness> <Access Kind>
    <Components>
    <Keyname>
    ©2010 SAP AG. All rights reserved. / Page 36
    非唯一性次键vs. 唯一性次键
    非唯一性(排序)次键
    懒惰索引更新(Lazy index update), 即:索引在被用到之前不会自动更新
    如果没有使用该索引,则不会消耗相应的内存空间
    因此,非常适合用于调整既有程序
    唯一性次键
    唯一性是一个语义上的约束, 也就是对于违反约束的原子操作(INSERT, MOVE, 
    SELECT, …)即刻做出反应(异常/运行时错误)
    ©2010 SAP AG. All rights reserved. / Page 37
    定义次键–实例
    ©2010 SAP AG. All rights reserved. / Page 38
    定义次键–ABAP字典
    ABAP 字典
    (SE11)
    新的标签项
    „Secondary Key“
    最多支持15个次键
    ©2010 SAP AG. All rights reserved. / Page 39
    数据库表中的次键vs. 内表中的次键
    数据库表
    优化器判定选择哪一个键
    一般情况下,结果集可按任意次序返回,  次序由SELECT语义决定
    内表
    定义好的内表条目次序
    标准表/哈希表:插入次序
    排序表:插入位置
    无法采用基于优化器的判定
    因此,需要显式指定要使用哪一个键
    ©2010 SAP AG. All rights reserved. / Page 40
    在有次键的内表上INSERT
    ABAP在内表插入语句(INSERT, SELECT … INTO, MOVE, …)中并没有针对次键的语
    法扩展
    由应用次键带来的性能提升是以适度增加内存消耗和键值更新为代价的:
    主键立即更新
    如果一个键值已经存在,则在向排序表和哈希表插入一条重复数据时并不更新主键
    (但语句返回值会置为非0)
    在批量重复插入时会产生运行时错误
    唯一性次键也会立即更新
    如果一个键值已经存在,则在向排序表和哈希表插入一条重复数据时会抛出可捕获的异常
    在批量重复插入时会产生运行时错误
    非唯一性次键采用懒惰更新(lazy update)
    只有当用该次键访问内表时,这些键才会被更新
    在使用该键之前没有额外的内存开销(除一些基本的程序管理开销)
    要避免使用不必要的次键
    ©2010 SAP AG. All rights reserved. / Page 41
    在有次键的内表上READ
    新的语法扩展… USING KEY KeyName…
    新的语法扩展… KeyNameCOMPONENTS …针对WITH从句
    在WITH从句中的次键组件须注意恰当使用
    对唯一性键值所有组件都必须指定
    对非唯一性键值必须指定其引导部分
    ©2010 SAP AG. All rights reserved. / Page 42
    在有次键的内表上LOOP
    新的语法扩展… USING KEY KeyName…
    新的语法扩展… USING KEY KeyName…针对WHERE从句
    在WHERE条件中指定次键的组件:
    comp
    1
    = val
    1
    AND … AND comp
    n
    = val
    n
    在WHERE从句中的次键组件须注意恰当使用(同READ WITH)
    其他的非键值组件可以由AND进行连接
    ©2010 SAP AG. All rights reserved. / Page 43
    其他支持次键的ABAP语句
    新的语法扩展… USING KEY KeyName…针对DELETE和MODIFY
    ©2010 SAP AG. All rights reserved. / Page 44
    主动键值保护
    主键:写保护
    排序表和哈希表的键组件是受到写保护的,不允许通过指针或引用更改键组件的值
    次键:
    在针对一个指定次键的loop当中,相关的键组件均被写保护
    在嵌套loop中, 所有主键及当前使用的相关次键的组件均被写保护
    技术上讲,这需要在所有写操作时对键组件进行监控
    当前没有使用的键的组件将会被覆盖(索引更新延迟进行)
    否则,如果所有次键的所有组件均处于写保护状态,则在向内表添加新的键值的时候会产生
    不兼容的后果
    ©2010 SAP AG. All rights reserved. / Page 45
    可应用次键的业务场景
    适合使用次键的业务场景
     超大表
     在最初表创建之后,没有或只有少量的表更新操作
     程序管理开销主要集中在创建表的阶段
     在使用次键之后性能提升显著
    使用唯一性次键的特殊应用场景
     需要重视数据完整性(唯一性)的程序
     小型内表
    以下情况不应使用次键
     小型内表(少于50条记录),系统开销和内存消耗另其得不偿失
     内表经常性地需要更新
    ©2010 SAP AG. All rights reserved. / Page 46
    总结–内表次键
    次键可以非常容易地与已有程序进行集成或在新程序当中应用以提高程序性能
     ABAP定义了一些语法扩展(USING KEY, COMPONENTS)以使用次键
     ABAP语法检查会对冗余及性能进行提示
     通过添加次键,既有程序的性能可以有效地提高,并且这些改动是上下兼容的
     懒惰更新(lazy update)及延迟更新处理提供了强大的增量处理能力
    ©2010 SAP AG. All rights reserved. / Page 47
    data:
    condition typestring.
    * construct condition string dynamically
    condition = |{ cname1 } >= { start } and | &
    |{ cname2 } <= { start } + { delta }|.
    * evaluateloopcondition completely at runtime
    loop at <itgeneric> assigning <line>
    where (condition).
    …
    endloop.
    另一些不同的情况…
    LOOP AT <itab> with dynamic WHERE condition
    动态工作
    区
    动态WHERE 条
    件
    通用内表
    如对数据库表操作的读取中所用到的动态WHERE条件一样, 这里我们需要:
    
    ABAP提供了非常广泛的通用及动态编程技术,但是有一个功能之前并未提供:
    ©2010 SAP AG. All rights reserved. / Page 48
    支持动态WHERE条件的LOOP语句
    动态WHERE条件与静态WHERE条件遵循同样的规则:
     操作符左边的操作数必须是内表行的一个组件
     操作符右边的操作数在LOOP到某一条记录时判定
    动态WHERE条件也可用于以下语句:
     MODIFY ... WHERE
     DELETE ... WHERE
    (规则同上)
    ©2010 SAP AG. All rights reserved. / Page 49
    data:
    condition typestring.
    * construct condition dynamically
    condition = |comp1 cp { val1} and | &
    |not comp2 < { val2 } or | &
    |comp3 = { val3} equiv comp4 = { val4}|.
    loop at <itgeneric> assigning <line>
    where (condition). 
    …
    endloop.
    动态WHERE条件的构造
    一个合法的条件构造如下:
    所有类型的算术和字
    符串操作
    布尔操作符:
    and, or, not, equiv
    ©2010 SAP AG. All rights reserved. / Page 50
    错误处理
    如果使用了不正确的WHERE条件,程序会在运行时抛出
    CX_SY_ITAB_DYN_LOOP异常:
    data:
    condition type string,
    excptype ref to cx_sy_itab_dyn_loop.
    * construct condition dynamically
    condition = |comp1 = { val1} ant | &
    |comp2 = { val2}|.
    try.
    loopat <itgeneric> assigning <line>
    where (condition).
    ...
    endloop.
    catch cx_sy_itab_dyn_loop intoexcp.
    " error handling
    endtry.
    条件不能正常解析: 
    unknown operator 
    ant
    ©2010 SAP AG. All rights reserved. / Page 51
    总结–动态WHERE条件
    动态WHERE条件可以使用以下结构条件:
     方法调用和成员变量
     运算表达式
     预定义方法
     数据引用
     动态WHERE支持次键
    性能表现:
     为避免内部类型转换问题,组件部分和值部分应使用相同数据类型.
     如果在WHERE条件当中恰当地使用了内表的键(排序键的第一个组件, 哈希键的所有
    组件),则该WHERE条件可以被优化
     作为一个内部优化,ABAP使用了缓存使得表的静态信息可以重用
    Demo 演示& 练习
    ©2010 SAP AG. All rights reserved. / Page 53
    课程安排
    1. 表达式
    2. 内表
    3. 基于类的异常处理
    4. 十进制浮点数
    5. 使用Locator和数据流读写数据库
    6. Boxed 组件
    ©2010 SAP AG. All rights reserved. / Page 54
    基于类的异常处理的几条原则
    将软件看成是(分层的)服务的集合
    服务发生错误时:
    没有程序上下文,并且可能无法纠正错误
    因此,只能发出错误标志,并且给出部分额外的错误信息
    中止程序并且把控制流交给合适的能够处理这种特殊情况的处理程序
    RAISE EXCEPTION TYPE CX_ORDER_LOCKED EXPORTING TEXTID = …
    静态地通知调用者可能要处理的异常
    METHODS readOrder … RASING CX_ORDER_LOCKED.
    将普通代码和错误处理程序分开: 分开定义异常处理程序
    TRY.
    order = readOrder( orderId ).
    CATCH CX_ORDER_LOCKED into excpobj.
    “ handle locked order situation
    ENDTRY.
    异常处理程序可以:
    停止操作
    继续操作, e.g. restart the service from the beginning RETRY
    ©2010 SAP AG. All rights reserved. / Page 55
    异常处理的例子
    METHOD a.
    TRY.
    b( ).
    CATCH cx.
    …
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    …
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    …
    RAISE
    EXCEPTION
    TYPE cx.
    …
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    堆栈
    代码
    1
    2
    3 4
    1
    2
    4
    cx的异常处理程序在方法a的执行上下文中调用!
    3
    
    ©2010 SAP AG. All rights reserved. / Page 56
    标准异常处理的局限
    以下几种情况下很难使用典型的异常
     处理大量数据: 子任务中的异常不能够终止整个任务
     收集错误: 捕获异常的方法必须捕获所有的错误
     纠正错误后重新启动: 继续正常的后续程序
     错误已经纠正(比如通过用户的交互)
     找到一个基于当前上下文的临时解决方案
    解决方案
     简单重试服务
     不自动终止服务
     从技术角度:不可以立刻退栈
    可恢复的异常
     抛出的异常必须是定义为“可恢复”的
     异常处理程序能决定是终止服务还是恢复服务
     服务必须是预定义为“可恢复”的
     分层的架构:所有的层都必须预定义为可传递“可恢复”的异常
    ©2010 SAP AG. All rights reserved. / Page 57
    在异常处理程序中使用RETRY
    一种可能的处理异常的办法就是重试...
    TRY.   
    CATCH cx_sy_file_access_error.
    ENDTRY.
    OPEN DATASET file FOR OUTPUT IN BINARY MODE.
    TRANSFER xbuffer TO file.
    CLOSE DATASET file.
    WRITE: 'Buffer successfully written'.
    IF ui->ask_for_retry(
    msg = 'No memory stick in port' )
    IS NOT INITIAL.
    RETRY.
    ELSE.
    WRITE: ‘Could not write buffer’.
    ENDIF.
    将控制交给定义当
    前异常处理程序的
    TRY模块
    ©2010 SAP AG. All rights reserved. / Page 58
    可保留上下文的异常处理程序: CATCH BEFORE 
    UNWIND
    恢复服务的前提: 必须保留上下文
     异常发生时不立即退栈
     没有执行CLEANUP的程序块
    新的CATCH 子句:
     异常发生时,退栈动作和CLEANUP程序块的执行将被推迟,直到异常处理程序执行
    完成
     因此,调用异常处理程序的时候需要保留原程序执行的上下文
     原程序的堆栈还包括所有有效的局部变量
     和在TRY…ENDTRY 里使用普通CATCH一样,使用相同的语法检查规则
    TRY.
    …
    CATCH BEFORE UNWINDcx_file_too_large INTO ex.
    msg = …   
    ENDTRY.
    ©2010 SAP AG. All rights reserved. / Page 59
    使用Catch Before Unwind的异常处理
    METHOD a.
    TRY.
    b( ).
    CATCH BEFORE
    UNWIND cx.
    ... 
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    ... 
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    ... 
    RAISE
    EXCEPTION
    TYPE cx.
    ... 
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    堆栈
    代码
    1
    2
    1
    2
    ©2010 SAP AG. All rights reserved. / Page 60
    使用Catch Before Unwind的异常处理
    METHOD a.
    TRY.
    b( ).
    CATCH BEFORE
    UNWIND cx.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    ...
    RAISE
    EXCEPTION 
    TYPE cx.
    ...
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    c
    b
    a
    1
    2
    3
    1
    2
    3
    堆栈
    代码
    ©2010 SAP AG. All rights reserved. / Page 61
    使用Catch Before Unwind的异常处理
    METHOD a.
    TRY.
    b( ).
    CATCH BEFORE
    UNWIND cx.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    ...
    RAISE
    EXCEPTION
    TYPE cx.
    ...
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    c
    b
    a
    1
    2
    3
    4
    5
    1
    2
    3
    4
    5
    堆栈
    代码
    ©2010 SAP AG. All rights reserved. / Page 62
    可恢复的异常
    抛出可恢复的异常:
    RAISE RESUMABLE EXCEPTION TYPE cx [ EXPORTING … ]
    RAISE RESUMABLE EXCEPTION object
    和RAISE EXCEPTION一样的语法规则
    抛异常的原程序需允许重启(恢复)
    Statement might or might not return
    定义为可恢复的处理程序:
    RESUME
    语法检查: 只可用在定义在CATCH BEFORE UNWIND里的处理程序
    不可恢复的异常使用RESUME会抛运行时错误(no-check exception 
    CX_SY_ILLEGAL_HANDLER with text id NOT_RESUMABLE)
    检查异常是否可恢复: ABAP_BOOL类型的属性IS_RESUMABLE
    如果控制流离开原处理程序而没有执行RESUME , 那么认为处理程序选择了“终止”,即执
    行退栈动作
    检查一个异常是否是可恢复的:
    IS_RESUMABLE
    这是异常根类CX_ROOT的成员变量, ABAP_BOOL类型, 只读
    ©2010 SAP AG. All rights reserved. / Page 63
    向上传递可恢复的异常
    让使用者知道可能发生的可恢复的异常:
    RAISING cx_1 | RESUMABLE(cx_1) …
    cx_n| RESUMABLE(cx_n) 
    此子句可用于methods, function modules 和forms 的定义
    CX_STATIC_CHECK 和CX_DYNAMIC_CHECK 类型的异常可向上传递,
    CX_NO_CHECK 不允许向上传递
    如果可恢复的异常没有在RAISING语句中的RESUMABLE关键字后列出,将会被作
    为普通(不可恢复)的异常抛出
    RESUMABLE(cx) 的含义为:当前异常可以被当作可恢复异常抛出,但不是强制的。
    在se24中的定义如图:
    ©2010 SAP AG. All rights reserved. / Page 64
    使用Resume的异常处理
    METHOD a.
    TRY.
    b( ).
    CATCH BEFORE
    UNWIND cx.
    RESUME.
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    ...
    RAISE RESUMABLE
    EXCEPTION
    TYPE cx.
    ...
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    1
    2
    1
    2
    堆栈
    代码
    ©2010 SAP AG. All rights reserved. / Page 65
    使用Resume的异常处理
    METHOD a.
    TRY.
    b( ).
    CATCH BEFORE
    UNWIND cx.
    RESUME.
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    ...
    RAISE RESUMABLE
    EXCEPTION
    TYPE cx.
    ...
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    c
    b
    a
    1
    2
    3
    1
    2
    3
    堆栈
    代码
    ©2010 SAP AG. All rights reserved. / Page 66
    使用Resume的异常处理
    METHOD a.
    TRY.
    b( ).
    CATCH BEFORE
    UNWIND cx.
    RESUME.
    ENDTRY.
    ENDMETHOD.
    METHOD b.
    TRY.
    c( ).
    CLEANUP.
    ...
    ENDTRY.
    ENDMETHOD.
    METHOD c.
    ...
    RAISE RESUMABLE
    EXCEPTION
    TYPE cx.
    ...
    ENDMETHOD.
    c
    b
    a
    b
    a
    a
    c
    b
    a
    1
    2
    3
    1
    2
    3
    4
    4 堆栈
    代码
    ©2010 SAP AG. All rights reserved. / Page 67
    总结–
    基于类的异常的新特性
    RETRY –有点小用
    CATCH BEFORE UNWIND
    本身自有的作用(用于检查堆栈,比如debug的时候)
    是使用可恢复的异常的前提
    可恢复的异常的三要素
    RAISE RESUMABLE EXCEPTION: service must allow resumption, and
    …RAISING(…): intermediate procedure must allow resumption, and
    RESUME: exception handler must choose resumption
    使用可恢复异常可以避免容易引起问题的异常处理方式,比如:
    使用标志位决定忽略错误,或者使用内表记录错误信息
    使用如logging的方式记录错误
    使用事件(event )报告错误
    Demo 演示& 练习
    ©2010 SAP AG. All rights reserved. / Page 69
    课程安排
    1. 表达式
    2. 内表
    3. 基于类的异常处理
    4. 十进制浮点数
    5. 使用Locator和数据流读写数据库
    6. Boxed 组件
    ©2010 SAP AG. All rights reserved. / Page 70
    二进制浮点数小数的问题(F)
    ABAP                   Type F
    Kernel (C/C++)    Type double
    输入 用F 类型表示
    (显示16位小数)
    保留小数点后2
    位数(四舍五入)
    期望值
    0.805 8.0500000000000005E-01 0.81 0.81
    0.815 8.1499999999999995E-01  0.81 0.82
    4.805  4.8049999999999997E+00 4.80 4.81
    4.815  4.8150000000000004E+00  4.82 4.82
     以2为底的小数如0.5, 0.25, 0.125, … 及其和可以被精确表示。
     大多以10为底的小数不可以被精确表示。
    ©2010 SAP AG. All rights reserved. / Page 71
    ABAP P 类型: 定点小数(BCD 数字)
    例子: 毫升和桶的相互转换
    使用6位小数: 
    1500.000000  ml
    0.009435  bbl.
    1500.045128 ml         5 位小数不精确
    使用最大14位小数:
    1500.00000000000000  ml
    0.00943471615138  bbl.
    1500.00000000071672 ml 依旧有5位小数不精确
    定点小数的问题(P)
    1 桶= 42 加仑= 9702立方英寸= 158.987295 升
    ©2010 SAP AG. All rights reserved. / Page 72
    ABAP中新的小数浮点类型
    基本类型: DECFLOAT
    此类型的实现使用了IBM‟s decNumber库。
    IBM 提供硬件支持。
    没有硬件的特殊支持,此类型的性能和类型P相近。
    此类型需要数据库提供商实现。
    类型 大小 十进制数位数 最小幂指
    数
    最大幂指
    数
    DECFLOAT16 8 Bytes 16 -383 384
    DECFLOAT34 16 Bytes 34 -6143 6144
    ©2010 SAP AG. All rights reserved. / Page 73
    可用十进制浮点数的服务
    DDIC, 可以和UNIT 和CUKY 类型配套使用.
    序列化(CALL TRANSFORMATION) 
    RFC / ALV / Web DynproABAP 
    ©2010 SAP AG. All rights reserved. / Page 74
    如何在数据库中存储Decfloat类型
    DF16_RAW / DF34_RAW
    SAP-proprietary format  
    序列化,SAP专有格式
    DB
    AppServer
    DECFLOAT16 / DECFLOAT34
    IEEE format
    数据库尚不支持新的IEEE 754-2008 
    类型.
    有三个可能解决方案(DDIC types). 
    DF16_DEC / DF34_DEC
    Fixed-point decimal format 使
    用定点小数存储
    DECFLOAT16 / DECFLOAT34
    IEEE format, NOT YET AVAILABLE 
    直接使用新标准数据类型尚不可行
    ©2010 SAP AG. All rights reserved. / Page 75
    如何在数据库中存储Decfloat类型
    --使用DF16_RAW / DF34_RAW
    将Decfloat16/Decfloat34 映射到RAW 类型
    SAP专有格式
    支持保留所有取值范围
    在DB中: 可以排序,可以比较
    在DB中: 可以作为键值数据类型
    不能保留Scale信息,尾部0会被删除
    不支持数据库大量数据集合处理:
    select sum(..)
    update tab set col= col+ val
    ©2010 SAP AG. All rights reserved. / Page 76
    如何在数据库中存储Decfloat类型
    --使用DF16_DEC / DF34_DEC
    将Decfloat16/Decfloat34 映射到DEC 类型
    (定点小数), 因此需要指定长度和小数位数
    在DB中:可以作为键值数据类型(包括缓冲区中的表)
    支持数据库大量数据集合处理
    select sum(..)
    update tab set col= col+ val
    不支持写入DB时对value range和value的约去
    可能导致写入时推迟溢出发生
    在where子句里使用有问题:
    10.00 <= 9.995
    可能导致溢出
    不保留尾数0
    ©2010 SAP AG. All rights reserved. / Page 77
    Round –约去方法
    新的内建方法round
    指定需要保留的小数尾数:
    round( val = my_value dec = my_dec ). 
    指定需要保留的十进制位数:
    round( val = my_value prec= my_prec ).
    dec和prec不可以同时指定.
    使用round 则意味着是使用类型DECFLOAT34 进行运算的.
    ©2010 SAP AG. All rights reserved. / Page 78
    Rescale –精确度调整方法
    例程 输出
    df = '12.3'.  df = rescale( val = df dec = 3 ).  12.300 
    df = '12.3005'. df = rescale( val = df dec = 3 ).  12.301 
    df = '12.3005'. df = rescale( val = df dec = 3
    mode = cl_abap_math=>round_half_even ). 
    12.300 
    df = '-2.3005'. df = rescale( val = df  dec = 3 ).  -2.301 
    df = '1.25005E-2'. df = rescale( val = df  dec = 3 ).  0.013 
    新的内置function rescale
    rescale function 可以约去尾数,也可以添加尾数0。
    roundfunction 只可以约去尾数。
    如果计算结果超出34个数字,rescale 将会抛异常
    cx_sy_operation_failure
    ©2010 SAP AG. All rights reserved. / Page 79
    输入的转换
    读取decfloat类型的值(WRITE TO 的反向操作):
    DATA:
    df TYPE DECFLOAT34,
    ex TYPE REF TO cx_abap_decfloat_parse_err.
    TRY.
    cl_abap_decfloat=>read_decfloat34(
    EXPORTING string = `-1,234,567.89`
    IMPORTING value = df ).
    CATCH cx_abap_decfloat_parse_err INTO ex.
    MESSAGE ex TYPE 'E'.
    ENDTRY. 
    Note: 读出数字的字符串格式由用户的设置决定
    ©2010 SAP AG. All rights reserved. / Page 80
    计算的精确度
    COMPUTE 语句的新附加关键字EXACT
    诸如+, -*, / 的运算符和诸如SQRT的内建方法在处理十进制浮点小数时几乎肯定会做约去操作:
    误差范围最多为0.5ULP(unit in the last place)
    相对误差最多为5E-34
    大多数情况下,约去操作是悄悄进行的。
    The EXACT 关键字使得用户可以侦查到一个语句是否可以被精确运算,约去操作是否是必须的。
    当语句不可以被精确运算,将抛出异常:
    TRY.
    COMPUTE EXACT result = 3 * ( 1 / 3 ).
    ... 
    CATCH cx_sy_conversion_rounding INTO exception.
    ...
    result = exception->value.
    ENDTRY.
    0.9999999999999999999999999999999999
    ©2010 SAP AG. All rights reserved. / Page 81
    性能
    类型decfloat的性能和类型P 的性能相近
    其实现基于IBM的decNumber库。
    IBM Power 6 processor has hardware support.
    类型F 由硬件支持,但是F <-> P 和F <-> C/String 的类型转换非常消耗资
    源。
    ©2010 SAP AG. All rights reserved. / Page 82
    ABAP数字类型的使用贴士
    1. 类型I
    适用于整数。如果类型I的取值范围不够,可以使用不带小数位的类型P 。如果还不
    够,可以使用十进制浮点小数。
    2. 类型P
    适用于小数数位固定的小数。如果取值范围不够,可以使用十进制浮点小数。
    3. 类型DECFLOAT16 和DECFLOAT34
    适用于小数数位不固定的小数或者取值范围很大的数字。类型decfloat16  使用的内
    存较少,但是运行时间和类型decfloat34 差不多。对于数据库访问,根据需要选择类
    型DFn_RAW或者类型DFn_DEC。
    4. 类型F
    仅仅适用于对精度要求不高,并且对性能有很高要求的算法。
    ©2010 SAP AG. All rights reserved. / Page 83
    总结
    Decfloat数据类型
    新的内建方法round和rescale
    使用cl_abap_decfloat 对输入进行转换
    使用由类cl_abap_math提供的辅助方法
    Decfloats可以用于
    Web DynproABAP
    Classic Dynpro
    ALV
    数据库中的Decfloat
    条件允许的情况下可以使用DF16_RAW / DF34_RAW
    (比如没有大数据量的数据库访问)
    有大数据量的数据库访问时,使用DF16_DEC / DF34_DEC 
    (使用此类型,取值范围会比较小)
    Demo 演示& 练习
    ©2010 SAP AG. All rights reserved. / Page 85
    课程安排
    1. 表达式
    2. 内表
    3. 基于类的异常处理
    4. 十进制浮点数
    5. 使用Locator和数据流读写数据库
    6. Boxed 组件
    ©2010 SAP AG. All rights reserved. / Page 86
    动机
    以前的Open SQL for ABAP支持LOB列
    DATA: my_string TYPE STRING.
    SELECT SINGLE content FROM dbtable_xxl
    INTO my_string
    WHERE id = 1.
    数据库对LOB提供更好的支持:Locators & Streams
    ©2010 SAP AG. All rights reserved. / Page 87
    Locators –概念
    Locator = 指向LOB列的值
    好处:避免或者减少实例化
    SELECT语句创建
     INSERT、UPDATE和MODIFY语句使用
    在一个DB事务结束的时候所有的Locator都会自动结束
    ©2010 SAP AG. All rights reserved. / Page 88
    读取一个LOB值
    1. 创建一个locator
    DATA: my_locator TYPE REF TO cl_abap_db_c_locator.
    SELECT SINGLE content FROM dbtable_xxl
    INTO my_locator
    WHERE key = 1.
    2. 在UPDATE SET语句中使用这个locator
    UPDATE dbtable_xxl
    SET content = my_locator
    WHERE key = 111.
    Locators –例子I
    ©2010 SAP AG. All rights reserved. / Page 89
    Locators –例子II
    Locator的方法:
    GET_LENGTH, FIND, GET_SUBSTRING, CLOSE
    DATA: clob_lng TYPE abap_msize,
    search_str TYPE string VALUE 'Read from here',
    found_pos TYPE abap_msize,
    result_str TYPE string.
    * Get length of the CLOB value
    clob_lng = my_locator->get_length( ).
    * Find start position of substring
    found_pos = my_locator->find( pattern = search_str ).
    * Read substring of CLOB value
    result_str = my_locator->get_substring(
    offset = found_pos
    length = clob_lng – found_pos ).
    * Close locator (and free associated DB resources)
    my_locator->close( ).
    ©2010 SAP AG. All rights reserved. / Page 90
    Streams –概念
    两个:Reader和writer Streams可以处理序列化数据
    数据可以根据需要部分读写
    由包含Streams的SQL语句产生的底层数据库操作,将会在所有
    Streams被显性关闭后才会结束
    一定要尽快的关闭Streams!
    ©2010 SAP AG. All rights reserved. / Page 91
    Streams –例子I
    从数据库到文件系统传输数据
    使用一个reader stream将一个LOB列的内容写到一个文件中去
    DATA: my_reader TYPE REF TO cl_abap_db_x_reader,
    my_size TYPE I VALUE 1024.
    * Create reader object
    SELECT SINGLE picture FROM lob_table
    INTO my_reader
    WHERE KEY = 1.
    * Open file
    OPEN DATASET 'my_file' FOR OUTPUT IN BINARY MODE.
    * Transfer data
    WHILE my_reader->data_available( ) = ABAP_TRUE.
    TRANSFER my_reader->read( my_size ) TO 'my_file'.
    ENDWHILE.
    * Close stream
    my_reader->close( ).
    ©2010 SAP AG. All rights reserved. / Page 92
    Streams –例子II
    从文件系统向数据库传输数据
    使用一个writer stream将一个文件写进一个LOB列
    DATA: my_writer TYPE REF TO cl_abap_db_x_writer,
    length TYPE I.
    container TYPE X LENGTH 1024.
    * Open file
    OPEN DATASET 'my_file' FOR INPUT IN BINARY MODE.
    * Create writer stream
    UPDATE lob_table SET picture = my_writer
    WHERE key= 1.
    * Transfer data
    DO.
    READ DATASET 'my_file' INTO container ACTUAL LENGTH length.
    IF SY_SUBRC <> 0. EXIT. ENDIF.
    my_writer->write( container ).
    ENDDO.
    my_writer->write( container(length) ).
    * Close stream
    my_writer->close( ).
    COMMIT WORK.
    ©2010 SAP AG. All rights reserved. / Page 93
    如果数据库表有许多LOB列,那么定义一个包含Streams和Locators的工作区域是非常费
    力的
    LOBHANDLE结构体
    TYPES wa_type TYPE lob_struct LOCATOR FOR COLUMNS lob1 lob2
    READER FOR COLUMNS lob3 lob4 lob5.
    WRITER和READER不能同时使用
    可以给数据库表和视图使用
    根据ABAP数据字典里的原表的描述,是可以生成相应的LOB HANDLE结
    构体
    STRING和RAWSTRING列可以更改成locators、readers或者writers.
    当ABAP数据字典里的原表的定义变化被激活的时候,LOB HANDLE结构
    体会自动更新
    ©2010 SAP AG. All rights reserved. / Page 94
    PK: Locators vsDB Streams
    用例 Locators Database Streams 
    读取
    搜索
    序列化处理
    读取子字符串
    读取整个内容
    降低内存
    ©2010 SAP AG. All rights reserved. / Page 95
    总结
    只有一个数据库服务器
    充分利用数据库表的缓存和索引
    通过跟踪SQL语句来检查他们的使用
    尽量坚持以下规则:
    减少Round Trips的次数
    通过好的索引来提高搜索命中率
    尽量使用精确查找
    降低传输数据量
    降低数据库负载
    Demo 演示& 练习
    ©2010 SAP AG. All rights reserved. / Page 97
    课程安排
    1. 表达式
    2. 内表
    3. 基于类的异常处理
    4. 十进制浮点数
    5. 使用Locator和数据流读写数据库
    6. Boxed 组件
    ©2010 SAP AG. All rights reserved. / Page 98
    动机
    问题:
    内存浪费在
    填充稀疏结构
    具有相同值的子结构
    结构的大小限制在512K
    需求:
    为相同值子结构和空的子结构进行内存优化
    解决方案:
    分开存储子结构
    按需分配内存
    ©2010 SAP AG. All rights reserved. / Page 99
    例子
    安全协议结构:
    
    Security Officer:
    Date:
    Incidents:
    If Yes:
    Room:
    Time:
    Description:
    Paul Safe
    Sep. 4
    th
    2008
    Yes
    12 A 5
    8:45 pm
    Window not closed
    ABAP里面的结构:
    TYPES:
    BEGIN OF security_struc,
    officer   TYPE C LENGTH 30,
    date      TYPE D,
    incidents TYPE ABAP_BOOL,
    room      TYPE C LENGTH 10,
    time      TYPE T,
    descr TYPE C LENGTH 200,
    END OF security_struc.
    ©2010 SAP AG. All rights reserved. / Page 100
    结构体的内存分布
    TYPES:
    BEGIN OF security_struc,
    officer   TYPE C LENGTH 30,
    date      TYPE D,
    incidents TYPE ABAP_BOOL,
    room      TYPE C LENGTH 10,
    time      TYPE T,
    descr TYPE C LENGTH 200,
    END OF security_struc.
    Officer D
    Room
    T
    Incidents
    Descr
    通常没有用到
    (if incidents = abap_false)
    每条记录存在216个空字符!
    ©2010 SAP AG. All rights reserved. / Page 101
    想法:通过数据引用来访问子结构
    TYPES:
    BEGIN OF security_struc,
    officer   TYPE C LENGTH 30,
    date      TYPE D,
    incidents TYPE ABAP_BOOL,
    details   TYPE REF TO detail_struc,
    END OF security_struc.
    Officer D
    Room Incidents
    每条记录只有一个空的数据引用!
    TYPES:
    BEGIN OF detail_struc,
    room  TYPE C LENGTH 10,
    time  TYPE T,
    descr TYPE C LENGTH 200,
    END OF detail_struc.
    T Descr
    ©2010 SAP AG. All rights reserved. / Page 102
    数据引用中的字段不能成为内表的主键:
    ... TYPE SORTED TABLE OF security_struc
    WITH UNIQUE KEY details->time.
    笨重的数据引用操作:
    IF security_entry-details IS INITIAL.
    CREATE DATA security_entry-details.
    ENDIF.
    ASSIGN security_entry-details->* TO <details>.
    垃圾收集器处理无用的数据对象(不是立即清除)
    带数据引用的数据结构不能在RFC里面使用,也不能在EXPORT功能里面使用
    数据引用的缺点
    语法错误
    TYPES:
    BEGIN OF security_struc,
    officer   TYPE C LENGTH 30,
    date      TYPE D,
    incidents TYPE ABAP_BOOL,
    details   TYPE REF TO detail_struc,
    END OF security_struc.
    TYPES:
    BEGIN OF detail_struc,
    room  TYPE C LENGTH 10,
    time  TYPE T,
    descr TYPE C LENGTH 200,
    END OF detail_struc.
    ©2010 SAP AG. All rights reserved. / Page 103
    解决方案:Boxed 组件
    Officer D
    Room Incidents
    每条记录只有一个空的数据引用!
    T Descr
    TYPES:
    BEGIN OF security_struc,
    officer   TYPE C LENGTH 30,
    date      TYPE D,
    incidents TYPE ABAP_BOOL,
    details   TYPE detail_struc BOXED,
    END OF security_struc.
    TYPES:
    BEGIN OF detail_struc,
    room  TYPE C LENGTH 10,
    time  TYPE T,
    descr TYPE C LENGTH 200,
    END OF detail_struc.
    ©2010 SAP AG. All rights reserved. / Page 104
    结构体中Boxed 组件的定义
    TYPES:
    BEGIN OF my_struct,
    ...
    boxed_component TYPE structure_type BOXED,
    ...
    END OF my_struct.
    必须是在TYPES语法里面定义
    Boxed类型必须是结构体的一部分、
    或者类的成员变量或者静态成员变
    量的一部分
    只有结构类型可用声明成为
    BOXED
    ©2010 SAP AG. All rights reserved. / Page 105
    类中Boxed 组件的定义
    CLASS lcl_my_classDEFINITION.
    PUBLIC SECTION.
    CLASS DATA:
    boxed_class_attribute TYPE structure_type BOXED.
    DATA:
    boxed_instance_attribute TYPE structure_type BOXED.
    ENDCLASS.
    Boxed类型必须是结构体的一部分、
    或者类的成员变量或者静态成员变
    量的一部分
    只有结构类型可用声名为BOXED
    ©2010 SAP AG. All rights reserved. / Page 106
    访问Boxed 组件
    Boxed Components可以象普通的结构一样访问:
    sec-details-time = sy-uzeit.
    lcl_security=>details-room = ’12 A 5’.
    Boxed Components可以提供类似普通结构一样有语义的值:
    lcl_security=>details-room = ’12 A 5’.
    sec-details = lcl_security=>details.
    lcl_security=>details-room = ’24 C 3’.
    sec-details-roomstill contains ’12 A 5’
    Boxed组件可以做为内表的主键
    Boxed组件可以在EXPORT功能和RFC中使用(必须使用basXML)
    TYPES:
    BEGIN OF security_struc,
    ...
    details TYPE
    detail_struc BOXED,
    END OF security_struc.
    DATA sec TYPE security_struc.
    CLASS lcl_security DEFINITION,
    PUBLIC SECTION.
    CLASS-DATA:
    details TYPE
    detail_struc BOXED.
    ENDCLASS.
    ©2010 SAP AG. All rights reserved. / Page 110
    Boxed结构的内容
    读取类型时初始化记录
    内存分配
    不会分配内存给boxed结构的语句:
    读:
    time = sec-details-time.
    引用根节点结构:
    ASSIGN sec TO <fs>.
    GET REFERENCE OF sec TO ref.
    会分配内存给boxed结构的语句:
    写:
    sec-details-time = sy-uzeit.
    引用boxed结构:
    ASSIGN sec-details TO <fs>.
    GET REFERENCE
    OF sec-details TO ref.
    参数传递:
    obj->meth( CHANGING
    details = sec-details ).
    初始化boxed 引
    用
    根结构
    Boxed 引用
    根结构
    初始化box:
    已分配的box:
    ©2010 SAP AG. All rights reserved. / Page 111
    总结
    如下情况不要使用boxed组件:
    结构中某一字段使用频率很高
    该结构长度小于100个Byte
    根结构被数据库表重用
    如下情况请使用boxed组件:
    结构中的字段通常不被使用,比如:
    存储下列情形的详细信息的时候
    –出错的时候
    –在给定某些可选参数的时候
    为某些很少使用的信息做缓存的时候
    为某个特定请求而使用的时候
    结构长度大于100个Byte
    Demo DEMO& EXERCISE 演示& 练习
  • 相关阅读:
    来自ebay内部的「软件测试」学习资料,覆盖GUI、API自动化、代码级测试及性能测试等,Python等,拿走不谢!...
    2000字谏言,给那些想学Python的人,建议收藏后细看!
    月薪20k+的测试工程师都会这项技能!
    Umbraco中的Member登录时的Lock out功能
    ASP.NET MVC中Session以及处理方式
    ASP.NET MVC 前端(View)向后端(Controller)中传值
    ASP.NET MVC程序传值方式:ViewData,ViewBag,TempData和Session
    Google中rel="canonical"的相关解释和用法
    虚拟攻防系统 HoneyPot
    JS一定要放在Body的最底部么? 聊聊浏览器的渲染机制
  • 原文地址:https://www.cnblogs.com/huangjianisgood/p/2788786.html
Copyright © 2011-2022 走看看