【问题标题】:Perl module sapnwrfc to retrieve data from a huge SAP table with RFC_READ_TABLEPerl 模块 sapnwrfc 使用 RFC_READ_TABLE 从一个巨大的 SAP 表中检索数据
【发布时间】:2017-04-19 13:48:03
【问题描述】:

我想使用 Perl 模块 sapnwrfc 从大型 SAP 表(数百万条目)中检索数据,然后将其导出为 CSV 文件。

这个想法是使用功能模块 RFC_READ_TABLE 如下:

# Connect to SAP system
# [...]
my $rd = $conn->function_lookup("RFC_READ_TABLE");
my $rc = $rd->create_function_call;
$rc->QUERY_TABLE("/PLMB/AUTH_OBSID");
$rc->DELIMITER("@");
$rc->FIELDS([ {'FIELDNAME' => 'OBJECT_ID'}, {'FIELDNAME' => 'SID'} ]);
$rc->OPTIONS([{'TEXT' => 'OBJ_TYPE = \'PLM_DIR\''}]);  
$rc->invoke;

# Iterate over $rc-DATA and export it to CSV file
# [...]
$conn->disconnect;

问题是脚本以内存不足错误终止,因为检索到的数据超出了现有内存。

是否有可能避免这个问题,比如分页机制或类似的东西?

【问题讨论】:

  • 欢迎使用 Stack Overflow 和 Perl 标签。请edit您的问题并附上您正在使用的模块的链接。它可能是metacpan.org/pod/sapnwrfc,但它有一个非常不常见的命名方案,所以最好是安全而不是抱歉。
  • 它是否告诉您该错误发生在哪一行?请包括确切的错误消息。迭代数据的部分可能也很有趣。我会假设如果你正确地逐行读取数据,它不会占用你所有的内存。

标签: perl sap


【解决方案1】:

基于SAP SCN 上的 Python 代码 sn-p,我找到了解决问题的方法。

使用功能模块 RFC_READ_MODULE 的导入参数 ROWSKIPS 和 ROWCOUNT 我可以获取包含行块的数据:

# Meaning of ROWSKIPS and ROWCOUNT as parameters of function module RFC_READ_TABLE:
#
# For example, ROWSKIPS = 0, ROWCOUNT = 500 fetches first 500 records, 
# then ROWSKIPS = 501, ROWCOUNT = 500 gets next 500 records, and so on. 
# If left at 0, then no chunking is implemented. The maximum value to either of these fields is 999999.
my $RecordsCounter = 1;
my $Iteration = 0;
my $FetchSize = 1000;
my $RowSkips = 0;
my $RowCount = 1000;

# Open RFC connection
my $conn = SAPNW::Rfc->rfc_connect;

# Reference to function module call
my $rd = $conn->function_lookup("RFC_READ_TABLE");

# Reference to later function module call
my $rc;

# Loop to get data out of table in several chunks
while ($RecordsCounter > 0){

    # Calculate the already retrieved rows that need to be skipped
    $RowSkips = $Iteration * $FetchSize;

    # Reference to function module call
    $rc = $rd->create_function_call;

    # Table where data needs to be extracted
    $rc->QUERY_TABLE("/PLMB/AUTH_OBSID");

    # Delimeter between columns
    $rc->DELIMITER("@");

    # Columns to be retrieved
    $rc->FIELDS([ {'FIELDNAME' => 'OBJECT_ID'}, {'FIELDNAME' => 'SID'} ]);

    # SELECT criteria
    $rc->OPTIONS([{'TEXT' => 'OBJ_TYPE = \'PLM_DIR\''}]);

    # Define number of data to be retrieved
    $rc->ROWCOUNT($RowCount);

    # Define number of rows to be skipped that have been retrieved in the previous fetch
    $rc->ROWSKIPS($RowSkips);

    # Function call
    $rc->invoke;

    $Iteration++;

    # Data retrieved        
    if(defined $rc->DATA->[0]){ 

      print "Fetch $Iteration\n";

      foreach my $TableLine ( @{ $rc->DATA } ) {
        print "$TableLine->{WA}\n";
      }

  }

  # No more data to retrieve
  else{

    # Leave loop
    $RecordsCounter = 0;
  }

}

# Disconnect RFC connection
$conn->disconnect;

【讨论】:

    【解决方案2】:

    这不是 RFC_READ_TABLE 的用途。您将不得不求助于其他一些提取方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      相关资源
      最近更新 更多