You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RPGLE外部过程返回多维数据结构时首行重复问题求助

问题

定义了一个返回dim(256)的OrderDs外部过程,调试时过程内数据正确,但主程序调用后,仅第一行数据被重复打印256次。执行OrderDs= getOrderDetails(iCusNo:iFrmDate:iToDate);后,OrderDs中所有元素均为第一行数据,循环处理也无效,请教如何正确获取外部过程返回的多维数据结构?

外部过程代码

**Free

dcl-proc getOrderDetails export;

   dcl-ds OrderDs dim(256) Qualified;
     ORDNO   zoned(5) inz;
     ORDDATE zoned(8) inz;
     LINNO   zoned(3) inz;
     ITMNO   zoned(5) inz;
     ITMQTY  zoned(5) inz;
   end-ds;

   dcl-pi *n likeds(OrderDs) dim(256);
     iCusNo zoned(5);
     iFrmDate zoned(8);
     iToDate zoned(8);
   end-pi;

   dcl-s sqlQuery2 varchar(1000);
   dcl-s v_RowsFetched Int(5) inz(0);

   sqlQuery2 = ' Select ORDS101A.ORDNO, ' +
               ' ORDS101A.ORDDATE, ' +
               ' ORDS102A.LINNO, ' +
               ' ORDS102A.ITMNO, ' +
               'ORDS102A.ITMQTY ' +
               'AS ITMQTY FROM ' +
               'ORDS101A JOIN ORDS102A ' +
               ' ON ORDS101A.ORDNO = ORDS102A.ORDNO ' +
               'WHERE ORDS101A.ORDDATE  '+ 
               'BETWEEN ? and ?' +
               ' and (ORDS101A.CUSNO = ?) ' +
              'order by ORDS101A.ORDNO,ORDS102A.LINNO';

     exec sql Prepare stmt2 from :sqlQuery2;
     exec sql declare OrdCursor scroll cursor for stmt2;
     exec sql open OrdCursor using  :iFrmDate, :iToDate, :iCusNo;

     Exec Sql fetch next from OrdCUrsor for 5 rows into :OrderDs;
     v_RowsFetched = sqlerrd(3);
     exec sql close OrdCursor ;

    return OrderDs ;
end-proc;

主程序代码

HDFTACTGRP(*NO) BNDDIR('MYBNDDIR1')

   FQSYSPRT   O    F  132        PRINTER

   **Free

    dcl-f ord101fm workstn;

    //**********************Variables Declaration********************//
    dcl-s iCusNo   zoned(5);
    dcl-s iFrmDate zoned(8);
    dcl-s iToDate  zoned(8);

    dcl-s pCusNam   char(30) inz;
    dcl-s pOrdNo    zoned(5) inz;
    dcl-s pOrdDate  zoned(8) inz;
    dcl-s pLinno    zoned(3) inz;
    dcl-s pItmno    zoned(5) inz;
    dcl-s pItmQty   zoned(5) inz;
    dcl-s Index     zoned(5) inz(1);
    dcl-s Sqlrows   Int(5)   inz(100);


    //*******************Procedures Declaration*******************  *//


    dcl-ds OrderDs dim(256) Qualified;
      ORDNO   zoned(5) inz;
      ORDDATE zoned(8) inz;
      LINNO   zoned(3) inz;
      ITMNO   zoned(5) inz;
      ITMQTY  zoned(5) inz;
    end-ds;


    dcl-pr getOrderDetails likeDs(OrderDs) extproc('GETORDERDETAILS');
      iCusNo zoned(5);
      iFrmDate zoned(8);
      iToDate zoned(8);
    end-pr;
   
    iCusNo= 1234;
    iFrmDate=20010912;
    iToDate=20030912;
    
    Clear OrderDs;
    OrderDs= getOrderDetails(iCusNo:iFrmDate:iToDate);

    EXCEPT HEADER;

    for index=1 to %elem(OrderDs);


      if OrderDs(Index).Ordno <> 0;
        index +=1;

        pCusNam    =  CustomerDs.oCusNam;
        pOrdNO     =  OrderDs(Index).ORDNO;
        pOrdDate   =  OrderDs(Index).ORDDATE;
        pLinno     =  OrderDs(Index).LINNO;
        pItmno     =  OrderDs(Index).ITMNO;
        pItmQty    =  OrderDs(Index).ITMQTY;

        EXCEPT Detail;
      endif;
    endfor;
   *Inlr=*On;

 //Printer File//
 OQSYSPRT   E            HEADER
 O
 O                                           30 'ORDER DETAILS REPORT'
 O          E            HEADER      1
 O                                           20 'Customer Name'
 O                                           35 'Order No'
 O                                           45 'Order Date'
 O                                           50 'Order Line'
 O                                           60 'Item Num'
 O                                           70 'Item Quantity'
 O                                          100 'Customer Number'
 O                                          120 'Price'
 O                                          130 'Total'
 O          E            Detail      1
 O                       pCusNam             30
 O                       pOrdNo              35
 O                       pOrdDate            45
 O                       pLinno              50
 O                       pItmno              60
 O                       pItmQty             70
 O                       iCusNo             100

问题分析与修复方案

1. 主程序循环逻辑错误(核心问题)

主程序for循环内的index +=1是导致数据重复/跳过的关键:

  • 初始index=1,进入if判断后先执行index +=1变为2,随后读取OrderDs(2)的数据
  • 下一次循环index自动递增到3,再次进入if又变为4,以此类推,直接跳过所有奇数索引的元素
  • 未被正确填充的数组后续元素会保留初始值或重复第一行数据,最终出现重复打印的现象

修复:删除if块内的index +=1,让for循环自动控制索引递增

2. 过程返回数据的优化

原过程仅fetch最多5行数据,且未返回实际获取的行数,建议:

  • 添加输出参数返回实际获取的总行数,避免主程序遍历整个256元素的空数组
  • 循环fetch直到无数据,确保所有符合条件的行都被填充到数组中

3. 其他细节修正

  • 主程序中CustomerDs未定义,需确保该数据结构已正确声明或替换为实际可用变量
  • 移除主程序中无效的注释代码

修改后的主程序循环部分

EXCEPT HEADER;

for index=1 to %elem(OrderDs);
  if OrderDs(Index).Ordno <> 0;
    pCusNam    =  CustomerDs.oCusNam; // 确保CustomerDs已正确定义
    pOrdNO     =  OrderDs(Index).ORDNO;
    pOrdDate   =  OrderDs(Index).ORDDATE;
    pLinno     =  OrderDs(Index).LINNO;
    pItmno     =  OrderDs(Index).ITMNO;
    pItmQty    =  OrderDs(Index).ITMQTY;

    EXCEPT Detail;
  endif;
endfor;

带返回行数的外部过程修改

**Free

dcl-proc getOrderDetails export;

   dcl-ds OrderDs dim(256) Qualified;
     ORDNO   zoned(5) inz;
     ORDDATE zoned(8) inz;
     LINNO   zoned(3) inz;
     ITMNO   zoned(5) inz;
     ITMQTY  zoned(5) inz;
   end-ds;

   dcl-pi *n likeds(OrderDs) dim(256);
     iCusNo zoned(5);
     iFrmDate zoned(8);
     iToDate zoned(8);
     oRowsFetched Int(5) options(*nopass:*output); // 添加输出参数返回实际行数
   end-pi;

   dcl-s sqlQuery2 varchar(1000);
   dcl-s v_RowsFetched Int(5) inz(0);
   dcl-s v_TotalRows Int(5) inz(0);

   sqlQuery2 = ' Select ORDS101A.ORDNO, ' +
               ' ORDS101A.ORDDATE, ' +
               ' ORDS102A.LINNO, ' +
               ' ORDS102A.ITMNO, ' +
               'ORDS102A.ITMQTY ' +
               'AS ITMQTY FROM ' +
               'ORDS101A JOIN ORDS102A ' +
               ' ON ORDS101A.ORDNO = ORDS102A.ORDNO ' +
               'WHERE ORDS101A.ORDDATE  '+ 
               'BETWEEN ? and ?' +
               ' and (ORDS101A.CUSNO = ?) ' +
              'order by ORDS101A.ORDNO,ORDS102A.LINNO';

     exec sql Prepare stmt2 from :sqlQuery2;
     exec sql declare OrdCursor scroll cursor for stmt2;
     exec sql open OrdCursor using  :iFrmDate, :iToDate, :iCusNo;

     // 循环fetch直到无数据,填充整个数组
     dow sqlcode = 0;
       Exec Sql fetch next from OrdCUrsor for 256 rows into :OrderDs;
       v_RowsFetched = sqlerrd(3);
       v_TotalRows += v_RowsFetched;
       if v_RowsFetched < 256;
         leave;
       endif;
     enddo;

     exec sql close OrdCursor ;

    // 返回实际获取的行数
    if %parms() >=4;
      oRowsFetched = v_TotalRows;
    endif;

    return OrderDs ;
end-proc;

优化后的主程序调用部分

// 更新过程声明,添加输出参数
dcl-pr getOrderDetails likeDs(OrderDs) extproc('GETORDERDETAILS');
  iCusNo zoned(5);
  iFrmDate zoned(8);
  iToDate zoned(8);
  oRowsFetched Int(5) options(*output);
end-pr;

dcl-s v_ActualRows Int(5) inz(0);

iCusNo= 1234;
iFrmDate=20010912;
iToDate=20030912;

Clear OrderDs;
OrderDs= getOrderDetails(iCusNo:iFrmDate:iToDate:v_ActualRows);

EXCEPT HEADER;

// 根据实际获取的行数循环,避免遍历空元素
for index=1 to v_ActualRows;
  pCusNam    =  CustomerDs.oCusNam;
  pOrdNO     =  OrderDs(Index).ORDNO;
  pOrdDate   =  OrderDs(Index).ORDDATE;
  pLinno     =  OrderDs(Index).LINNO;
  pItmno     =  OrderDs(Index).ITMNO;
  pItmQty    =  OrderDs(Index).ITMQTY;

  EXCEPT Detail;
endfor;

内容的提问来源于stack exchange,提问作者Rituraj singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:45:53