wenmo8 发布的文章

 

ALE技术:应用链接支持(Application Link Enabling 简称ALE),是一项用于创建和运行分布式应用的技术。ALE是SAP的专有技术。

ALE对象——ALE包含了可控的数据消息交换,可以确保松散耦合的应用程序之间的数据一致性。ALE由三层组成,应用服务、分发服务和通信服务。ALE的基本原理是提供一个分布式的并且完全整合的R/3系统。每一个应用都是自适应的。每一个自适应系统使用一种特定的方法实现数据冗余。因此数据必须是分布的、且同步的。

 

ALE通信图

 

1,IDOC类型和消息类型的区别是什么?如何联系IDOC类型和消息类型?

消息类型把意义赋予了IDOC,IDOC类型则将结构给予了IDOC。消息会在包含着不同消息类型的系统之间交换。消息类型依赖于包含的数据和涉及的处理过程,它决定了消息的技术结构和IDOC类型。IDOC类型标识了SAP用于解释一个busness transaction的格式。

 

2,IDOC信息存储在哪里?

描述

EDID4

存储数据记录 (version 4.6)

EDIDC

存储IDOC的控制记录信息

EDIDD

数据段 (EDI中间文档)

EDIDS

存储IDOC的状态

3,处理代码是什么?处理代码的类型是什么?

处理代码是指一个可以帮助从/向IDOC读写数据的workflow或者是function module。处理代码应用在ALE和EDI中,用以标识需要被调用以进行后续处理过程的function  module或者API。进站和出站接口也使用处理代码,但是用于不同的目的。出站处理代码保存在表TEDE1中,而进站处理代码保存在TEDE2中。

以下是处理代码类型。

 

处理代码

描述

Inbound Process Code

This will Idoc and create corresponding application data

Outbound Process Code

读取应用数据并放置到IDOC中

Status Proces Code

处理IDOC被发送到其它系统时出现的错误

System Process Code

创建工作条目,如果在IDOC/应用文档处理中发生某些错误的情况下

 

4,如何处理IDOC?

你可以使用以下程序来处理IDOC:

  • RBDMANI2 : 手动重新处理IDOC
  • RBDMANIN : 发送状态51的IDOC
  • RBDMOIND : 状态03->12的出站IDOC
  • RSEOUT00 : 处理状态30的IDOC
  • RBDAPP01 : 处理状态64的IDOC
  • RBDAGAIN : 重新处理不正确的出站IDOC
  • RBDAGAI2 : 重新处理ALE输入错误的IDOC

 

5,如何从发送系统追踪接收系统的IDOC?

  • 运行事务代码BD87
  • IDOC编号字段填入出站IDOC,然后运行。或者当你运行主数据事务比如说BD10的时候,记住开始时间和结束时间并且填到BD87的相应字段里面,并且给出消息类型接收系统的名字,然后运行
  • 选择相应的消息类型,然后点击追踪IDOC按钮

 

6,如何基于数据追踪IDOC?

步骤:

  •  运行事务代码WE09
  •  把消息类型名填入字段“逻辑消息”,比如,填上“DEBMAS”
  •  现在我们要移动到“在数据记录中的搜索标准”部分
  •  在这部分我们要填入段的名字,即我们想要搜索的数据的段名,填入到“在段中搜索”中。比如,填上“EX - E1KNA1M”
  •  在“在字段中搜索”字段中,我们要填入想要搜索的数据段的字段名,比如用“KUNNR”来搜索特定的客户编码对应的IDOC。
  •  现在在字段“”中我们要填入搜索值。比如,客户编码“100”。
  •  我们现在要运行事务。 
  •  结果可以是单个IDOC或者多个IDOC的列表,这取决于输入的搜索条件。

7,如何在同一个系统里面发送和接受IDOC?

  • 创建一个虚拟的逻辑系统
    • 新条目。前往事务代码 SALE->基本设置->逻辑系统->新条目,输入SYSID_CLNT,但是这个是虚拟的,所以使用SYSID的前两个字符和前缀“D”,接着加上下划线和客户端号。(注:原文是SALE-> sending and Receiving Systems -> Logical Systems ,疑有误)。

  例如,如果ERP_100是R/3的逻辑系统,创建的虚拟系统名应该是ERD_100.

  •  为源系统创建端口(ERP_100)
    • 前往WE21并且选择“事务性RFC”然后点击创建按钮。将端口命名为“SAP”并且把它和SYSID结合到一起,在我们的例子里应该是SAPERP。选择合适的版本,输入当前系统的RFC连接,在这个例子里是“ERP”。
  • 在合作伙伴类型LS里创建合作伙伴配置:
    • 接收端 ( Outbound to ) : 在合作伙伴类型LS,编号ERD_100中创建出站参数,给出消息类型,接收端名(即我们在第二步中创建的)。输入基本类型。
    • 发送端( Inbound From ): 在合作伙伴类型LS,编号ERD_100中创建入站参数,给出合适的消息类型和处理代码。
  • 现在创建单独的程序来发送IDOC:
    • 程序需要在某个点调用FM: MASTER_IDOC_DISTRIBUTE,这时需要传递如下的EDIDC结构:
      i_edidc-mestyp = 消息类型.
      i_edidc-idoctp = 基本类型.
      i_edidc-rcvprt = 'LS'.
      Concatenate 'SAP' sy-sysid into l_port.  
      i_edidc-rcvpor = l_port.
      i_edidc-rcvprn = 'ERD_000'.
      CONCATENATE sy-sysid '_' sy-mandt
      INTO l_sndprn.
      i_edidc-sndprn = l_sndprn.
      i_edidc-sndprt = 'LS'.
      i_edidc-sndpor = l_port.
    • 观察发送端口和接收端口,这是关键所在。出站IDOC通过名为ERP_100的发送者被发往端口SAPERP,接收者为ERD_100,接着入站IDOC也通过发送者ERP_100被发往相同的端口SAPERP,接收者仍是ERD_100.

 

8. 消息控制是什么?什么时候使用它?

消息控制是一种根据选择条件和需求来输出文档的机制。该原理并非只应用在EDI和ALE中,也在其它的输出媒介(比如:打印,传真)中使用。消息控制会判断文档类型、时间、数量和媒介。NAST表存储了输出记录。用于创建输出消息的条件(选择条件和需求)存储在条件表里。搜索机制用于访问队列、输出结果以及判断应用文档是否有资格被输出。

 一些有关消息控制的T-CODE:

事务代码

 描述

NACE

条件记录维护

VOK2

SD消息控制组件

VOK3

采购消息控制组件

VOFM

关于需求、公式的配置

V/86

条件表字段目录

WE15

IDOC测试:从消息控制出站测试

 

9,如何重新处理失败的传输条目?

你可以使用程序RSARFCEX重处理失败的传输条目。

 

10,可以在用哪个事务代码在统一额地方找到出站和入站处理代码?

WE64

 

本文链接:http://www.cnblogs.com/hhelibeb/p/6625534.html

英文原文:ALE, IDOC

 

IDOC的参考:

IDoc

IDoc Basics For Functional Consultants

 

最近,我在玩ABAP CDS视图,并且遇到了一些权限方面的挑战。我在网上没看到有多少有关CDS开发的文档,因为它是个相当新的东西。因此,我决定写下这篇博客,也许我的想法可以帮助到一些人。

 

和你已经意识到的一样,ABAP CDS视图跑在ABAP层,而且不受限于SAP HANA(也就是不存在这样的数据库依赖)。ABAP CDS有它自己的、基于角色的权限概念。角色通过DCL源代码中的DEFINE ROLE定义。

 

这里是一个基本的CDS视图,它有数据目录“dimension”

 

当我在HANA STUDIO中运行CDS视图的时候,我观察到这个查询没有抓取到成本中心数据。为什么?

 

每个CDS视图都在SE11中有它相对应的SQL视图。在上面的例子中。IFICostCenter是DDL I_CostCenter的SQL视图。

 

这里有一个找到这些对象定义所在的包的简单方法,

前往SE11输入视图,IFICostCenter >显示:

 

你可以在这里找到包名(上图高亮的部分)。

 

现在打开HANA Studio,把这个包添加到你的包收藏夹文件夹。

 

一旦添加到了你的收藏夹,展开Core Data Services然后你就可以在数据定义文件夹看到DDL源代码,以及在访问控制文件夹看到DCL源。

 

这里是一个成本中心CDS视图的DCL源的例子。

注意:DDL和DCL的名字必须一致。

 

权限在DCL源中执行了。我们应该确保权限对象K_CSKS在后端被分配到用户(在我使用的S/4 HANA 1511中是这样的)。

 

将权限检查对象授予给用户之后,可以看到成本中心数据了,Bingo!

 

注意:actvt是操作代码。在该情况下,应该是03——显示。

 

注释@AccessControl.authorizationCheck: #CHECK 会强制进行权限检查。

如果使用#NOT_REQUIRED 或 #NOT_ALLOWED,权限检查会被忽略。

 

 

希望本文对你有帮助。

 

本文链接:http://www.cnblogs.com/hhelibeb/p/6647178.html

英文原文:Wonder how Data Control Language (DCL) works with ABAP Core Data Services (CDS)?

 

 

面向对象事件在ABAP中十分重要,并且很容易处理。

我们需要handler方法来注册事件:

 

METHODS : handle_event_raised FOR EVENT event_raised OF lcl_event_raiser.

 

哪些工具可以用于性能优化?

ST05-性能追踪。包含SQL追踪加RFC,队列和缓存追踪。SQL追踪主要用于测量程序中select语句的性能。

SE30-运行时分析。用于测量应用的性能。

SAT是过时的SE30的替代品。提供了和SE30相同的功能和额外的一些特性。

ST12事务(ST-A/PI软件组件的一部分)是ST05和SAT的结合。这是个非常强大的性能分析工具,由SAP提供支持。

Code Inspectior(SCI)是最好的静态性能分析工具之一。有很多选项可以用于找到通常的错误和可能的性能瓶颈。

优化ABAP代码的步骤

1,数据库

a. 在select语句中使用使用where子句来限制数据检索的体积。很重要!(译注:工作中见到过有人写select * from marc这种语句. 导致在生产系统中直接因为内存不足dump)

b. 设计查询,使其尽可能多地在where中使用索引字段。

c. 在select语句中使用inner(或者某些情况下使用outer)join语句以实现一次性查询得到匹配的数据。

d. 避免使用嵌套的select语句,以及loop中的select语句,使用join或者for all entries in会更好。如果已经有内表可以使用,或者在某些处理结束之后,可以使用for all entries in。如果select后面正好还有选择的话,使用join。

e. 访问缓存时避免使用into corresponding fields of table。相反,应该使用最适合程序的(字段)。

f. 避免使用select * ,应该只查询需要的字段。

g. 不要在select语句中使用order by,如果它和用到的索引不同的话(正确的做法是排序内表)。因为这会增加很多额外的工作。数据库系统只有一个,而ABAP服务器有好多。(译注:不确定这种观点在HANA平台中是否依旧适用。可以参考一篇在SCN上的问答,ABAP7.51版本的文档中已经删除了这个限制相关的描述:ABAP Development : SAP HANA ORDER BY or SORT internal table

h. 索引。在为了改善性能而创建索引前,需要深思熟虑。索引可以提高查询性能,但是也会带来两个间接的负担:存储空间和写入性能。在大事务表中创建索引时,用于存储索引的空间和索引的体积是非常巨大的!当在数据库表中插入一条新的记录的时候,所有索引都需要更新。索引越多,花费的时间也就越多。数据越多,索引也就越大,更新索引所需的时间也就越大。

i. 避免多次运行相同的select(同样的select, 同样的参数)。在你的abap代码中缓存相关信息。

j. 如果有不影响性能的标准的视图,避免使用join语句。

2,表缓存

a. 将表定义为“缓冲过的”(SE11)可以提高性能,但是要小心地使用它。表的缓存会导致程序从缓存中而不是表中读取数据。缓存和表是周期性同步的,只有极少情况下、某些东西改变的时候才会同步。如果是事务表,数据在不同的选择条件下会改变,因此这类表是不适合缓存的。不建议在这种情况下使用缓存。应该为配置表和某些主数据表启用缓存

b. 避免对缓存表使用复杂的查询,因为SAP可能解释不了这个请求,并且也许会把它传递给数据库——code inspector可以说明哪些命令会绕过缓存。

3,内表

a. 尽可能使用哈希表,其次是排序表。标准表是最后的选择。

b. 如果要修改内表的话,对于大工作区,应使用assign而不是loop into

c. 有疑问的时候,运行SE30,以此检查代码

d. 如果不得不用标准表,并且要read读取其中的行的话,使用binary search来提高搜索速度。

4,杂项

a. perform:写子程序的时候,总是提供所有参数的类型。这减少了系统根据形参确定参数类型的开销。这也提高了程序的健壮性。

select single和select ... up to 1 rows的区别是什么?

  • select single和select up to 1 rows返回第一条匹配给定条件的记录。它可能不是唯一的,给定条件有可能匹配多条记录。
  • 对于oracle数据库而言,select single会被转换为select ... up to 1 rows,因此,它们是一样的。只不过ABAP的语法不允许将order by和select single放在一起用,但是允许其和select...up to 1 rows一起用。因此,如果你想获得最高/最低的一条记录,是不可以用select single的,只能用select ... up to 1 rows where ... order by.

join和for all entries in哪个性能好?

绝大多数场景下,inner join比for all entries in要好,应当被首先采用。只有当可能出现性能问题的时候才要用for all entries in,要仔细地测量更换为for all entries in前后的性能变化以验证是否真的有提升。

需要首先在一个测试程序上运行for all entries in并运行sql追踪以观察其效果。某些由BASIS设定的选项可以使for all entries in作为“OR”条件运行。这意味着如果使用for all entries in筛选的表有3条数据

,SQL追踪会显示3个SQL在执行。在这种情况下,使用for all entries in没意义。然而如果SQL追踪显示一条SQL语句,这时for all entries in是有用的,因为它实际上被当作一个in列表来执行。

比起for all entries in,更加推荐使用join。join连接的表的数量并没有实际的限制;不过太复杂的句子会难以维护,如果join里面有什么问题,也比较难以解决。如果join是使用两个表的键来连接的话,会减少程序负担,提高性能。

在某些场景下,你会需要以内表作为条件。此时,你可能没别的选择,只能用for all entries in了。

下面是使用了join的代码:

 

SELECTA~VBELN A~KUNNR A~KUNAG B~NAME1INTO TABLEI_LIKPFROMLIKP AS A
INNER JOIN KNA1 AS B
ON A~KUNNR =B~KUNNR.*For with limited data using for all entries:*Minimize entries in I_likp by deleting duplicate kunnr. LOOP AT I_LIKP INTOW_LIKP.
W_LIKP2
-KUNAG = W_LIKP-KUNAG.APPEND W_LIKP2 TOI_LIKP2.ENDLOOP.SORT I_LIKP2 BYKUNNR.DELETE ADJACENT DUPLICATES FROMI_LIKP2 COMPARING KUNNR.*GET DATA FROM kna1 IF NOT I_LIKP2[] IS INITIAL.SELECTKUNNR NAME1INTO TABLEI_KNA1FROMKNA1FOR ALL ENTRIES INI_LIKP2WHERE KUNNR = I_LIKP2-KUNNR.ENDIF.

 

在ABAP中,存在着一条法则:名字不一定代表实际规则(具体可看最近的相关讨论)。

但是如你们所知的,存在着一个很好的例外: 所有涉及到使用CORRESPONDING为结构赋值的关键字的语法形式(偶然地)有着相同的名字..

  • 在ABAP 7.40之前,主要有用MOVE-CORRESPONDING来复制结构组件、Open SQL的SELECT的CORRESPONDING附加字段,以及某些过时的计算语句等。
  • 在ABAP 7.40中,MOVE-CORRESPONDING可以用于操纵带有结构的内表。并且7.40引入了一个新的构造器操作符CORRESPONDING,它允许显式地将结构的组件映射到不同名字的组件上。

还缺了点什么?答案是动态的映射!这个特性在ABAP 7.50中得到了引入。

新的系统类  CL_ABAP_CORRESPONDING允许你适用动态指定的映射规则为结构或内表的组件赋值。

映射规则需要创建在一个映射表中,然后传递给映射对象。

例子如下:

DATA(mapper) =cl_abap_corresponding=>create(

source
=struct1

destination
=struct2

mapping
= VALUE cl_abap_corresponding=>mapping_table(

( level
= 0kind= cl_abap_corresponding=>mapping_component

srcname
=‘…’

dstname
=‘…’ )

( level
= 0kind= cl_abap_corresponding=>mapping_component

srcname
=‘…’

dstname
=‘…’ )

( level
= 0kind= cl_abap_corresponding=>mapping_component

srcname
=‘…’

dstname
= ‘…’ ) ) ).