简体   繁体   English

在 rpgle 中将 cursor 提取到数组中的性能缓慢

[英]slow performance of fetch cursor into array in rpgle

I have this relatively simple rpg program where the line exec sql workKeySocWorkCodesCur for 500 rows into:childWorkKeyArray;我有这个相对简单的 rpg 程序,其中行exec sql workKeySocWorkCodesCur for 500 rows into:childWorkKeyArray;

is performing very slowly.表现非常缓慢。 It tales about 6 seconds to execute each time.每次执行大约需要 6 秒。 What I dont understand is when I run this query interactively or when I tested this statement in a separate RPG containing only this statement (by substituting the host variable values), it seems to complete in less than a second.我不明白的是,当我以交互方式运行此查询时,或者当我在仅包含此语句的单独 RPG 中测试此语句时(通过替换主机变量值),它似乎在不到一秒钟内完成。 So what difference in this program might be causing it to slow down?那么这个程序有什么不同可能导致它变慢呢?

**FREE
// ******************************************************************
// Globals
// ******************************************************************

dcl-ds  parentWorkKeyArray         qualified dim(500);
          workKey              like(P_IacWrkKey.WorkKey) inz(0);
          workIsRef            char(1) inz (*blanks);
          workKeyParentKey     like(P_IacWrkKey.WorkKey) inz(0);
end-ds;

dcl-ds  childWorkKeyArray          qualified dim(500);
          workKey              like(P_IacWrkKey.WorkKey) inz(0);
          workIsRef            char(1) inz (*blanks);
          mergedToWorkKey      like(P_IacWrkKey.WorkKey) inz(0);
end-ds;


dcl-ds ISWCDUPDS                          Extname('POTISWCDUP') qualified;
end-ds;

dcl-s  merged                    ind inz(*off);
dcl-s  multipleActiveWorksPresent   ind inz(*off);
dcl-s  countOfNonReferencedWorks int(5);
dcl-s  index                              int(5) inz(1);
dcl-s  isChildWorkKeySameAsParent         int(5);
dcl-s  isChildWorkKeyMergedToParent       int(5);
dcl-s  socCodeFound                       ind inz(*off);
dcl-s  socCodeTBMFound                    ind inz(*off);
dcl-s  pos                                int(5);
dcl-s  gCheckSqlKeyField                  varchar(128);
dcl-s  check                              char(3);
dcl-s  socWorkCodeString                  like(ISWCDUPDS.ISWCSOCWCD);
dcl-s  iswcReference                      like(ISWCDUPDS.ISWC);

dcl-c firstElement const(1) ;


// ------------------------------------------------------------------------
// Program procedure flow
// ------------------------------------------------------------------------
dcl-pi *n end-pi;

exec sql SET OPTION COMMIT = *NONE ;

if not BeginProgram();
  ErrorHandling();
  return;
elseif not ProcessRequest();
  ErrorHandling();
  return;
endif;
*inlr = *On;
return ;

//  ------------------------------------------------------------------------
//  * Procedure name: ProcessRequest
//  * Purpose:        Process Request
//  * Returns:        True or False
//  *------------------------------------------------------------------------

dcl-proc ProcessRequest;

    dcl-pi *N ind end-pi;

    dcl-s referenceType  char(10);

    exec sql close potiswccur;
    exec sql open potiswccur;

    exec sql fetch first from potiswccur into :ISWCDUPDS;

   dow (sqlcod = 0);

      if not GetIswcWorkKeys();
        return cFalse;
      endif;

      referenceType = 'ISWC';
      if not CheckIfISWCMergdToISWCTBM(referenceType);
        return cFalse;
      endif;

      GetWorkKeyString(referenceType);

      if not GetSocietyWorkCodeWorkKeys();
        return cFalse;
      endif;

      referenceType = 'SOC';
      if not CheckIfISWCMergdToISWCTBM(referenceType);
        return cFalse;
      endif;

      GetWorkKeyString(referenceType);

      UpdateRecord();

      exec sql fetch next from potiswccur into :ISWCDUPDS;

   enddo;

   return cTrue;

end-proc ProcessRequest;


//  ------------------------------------------------------------------------
//  * Procedure name: getWorkKeyStringSocCode
//  * Purpose:        Combines all work keys into a string delimited by '|'
//  * Returns:        True or False
//  *------------------------------------------------------------------------

dcl-proc getWorkKeyString;

   dcl-pi *n ind ;
    referenceType char(10);
   end-pi;

   index = 1;

   dow (index < 500);

        if ( parentWorkKeyArray(index).workKey <> 0);
            if (referenceType = 'ISWC');
                if (index > 1);
                    ISWCDUPDS.IWKEY_ISWC = %Trim(ISWCDUPDS.IWKEY_ISWC)  + '|';
                endif;
                ISWCDUPDS.IWKEY_ISWC = %Trim(ISWCDUPDS.IWKEY_ISWC) + %char(parentWorkKeyArray(index).workKey);
            else;
                if (index > 1);
                    ISWCDUPDS.IWKEYSOCD = %Trim(ISWCDUPDS.IWKEYSOCD)  + '|';
                endif;
                ISWCDUPDS.IWKEYSOCD = %Trim(ISWCDUPDS.IWKEYSOCD) + %char(parentWorkKeyArray(index).workKey);
            endif;
        endif;

        if ( childWorkKeyArray(index).workKey <> 0);
             if (referenceType = 'ISWC');
                if (index > 1);
                    ISWCDUPDS.IWKEYMISWC = %Trim(ISWCDUPDS.IWKEYMISWC)  + '|';
                endif;
                ISWCDUPDS.IWKEYMISWC = %Trim(ISWCDUPDS.IWKEYMISWC)  + %char(childWorkKeyArray(index).workKey) ;
             else;
                if (index > 1);
                    ISWCDUPDS.IWKEYSOCDM = %Trim(ISWCDUPDS.IWKEYSOCDM) + '|' ;
                endif;
                ISWCDUPDS.IWKEYSOCDM = %Trim(ISWCDUPDS.IWKEYSOCDM) + %char(childWorkKeyArray(index).workKey) ;
             endif;
        endif;

      index = index + 1;

   enddo;
   return cTrue;
end-proc;


dcl-proc GetSocietyWorkCodeWorkKeys;

dcl-pi *n ind ;

      end-pi;

      clear parentWorkKeyArray;
      clear childWorkKeyArray;

      // declare cursor for fetching work keys of ISWC
      socWorkCodeString = ISWCDUPDS.ISWCSOCWCD ;
      exec sql close workKeySocWorkCodesCur;
      exec sql open workKeySocWorkCodesCur;
      exsr checkSQLCodeSR;

      exec sql fetch workKeySocWorkCodesCur for 500 rows into :parentWorkKeyArray;
      exsr checkSQLCodeSR;

      // declare cursor for fetching work keys of ISWC TBM
      socWorkCodeString = ISWCDUPDS.TMSOCWRKCD ;
      exec sql close workKeySocWorkCodesCur;
      exec sql open workKeySocWorkCodesCur;
      exsr checkSQLCodeSR;

      exec sql fetch workKeySocWorkCodesCur for 500 rows into :childWorkKeyArray;
      exsr checkSQLCodeSR;

      return cTrue;

      begsr checkSQLCodeSR;
          if not CheckSqlCode(sqlcode:sqlwarn(1):gCheckSqlKeyField);
              return cFalse;
          endif;
      endsr;

end-proc;

//----------------------------------------------------------------------------------------------
// Procedure name: GetIswcWorkKeys
// Purpose:        Fetches work keys to which ISWC and ISWC_TBM are allocated and
//                 places them in parentWorkKeyArray and  childWorkKeyArray respectively
// Returns:        Successful/unsuccessful action
//----------------------------------------------------------------------------------------------

dcl-proc GetIswcWorkKeys;

      dcl-pi *n ind ;

      end-pi;

      clear parentWorkKeyArray;
      clear childWorkKeyArray;

      // declare cursor for fetching work keys of ISWC
      iswcReference = ISWCDUPDS.ISWC ;
      exec sql close workKeyISWCCur;
      exec sql open workKeyISWCCur;
      exsr checkSQLCodeSR;

      exec sql fetch workKeyISWCCur for 500 rows into :parentWorkKeyArray;
      exsr checkSQLCodeSR;

      // declare cursor for fetching work keys of ISWC TBM
      iswcReference = ISWCDUPDS.ISWC_TBM ;
      exec sql close workKeyISWCCur;
      exec sql open workKeyISWCCur;
      exsr checkSQLCodeSR;

      exec sql fetch workKeyISWCCur for 500 rows into :childWorkKeyArray;
      exsr checkSQLCodeSR;

      return cTrue;

      begsr checkSQLCodeSR;
          if not CheckSqlCode(sqlcode:sqlwarn(1):gCheckSqlKeyField);
              ErrorHandling();
              return cFalse;
          endif;
      endsr;

end-proc;

//---------------------------------------------------------------------
// Procedure name: checkIfISWCMergdToISWCTBM
// Purpose:        checks if both sides of the pair are merged
// Returns:        Successful/unsuccessful action
//---------------------------------------------------------------------

dcl-proc checkIfISWCMergdToISWCTBM;

    dcl-pi *n ind;
        referenceType char(10);
    end-pi;

    dcl-s workKeysFound ind;
    dcl-s workKeysTBMFound ind;
    dcl-s multipleActiveWorksPresent ind;
    dcl-s merged ind;

    if not checkNumberOfActiveWorksOnISWC(multipleActiveWorksPresent);
         return cFalse;
    endif;

    if not multipleActiveWorksPresent;

        if not checkIfWorkCodesFound(workKeysFound: workKeysTBMFound: referenceType);
            return cFalse;
        endif;

        if (workKeysFound and workKeysTBMFound);
            checkIfChildCompletelyMergedToParent(merged);
         endif;

        if merged;
            if referenceType = 'ISWC';
                ISWCDUPDS.ISWCSORM = 'MERGED';
            else;
                ISWCDUPDS.SOCCSORM = 'MERGED';
            endif;
        else;
            if referenceType = 'ISWC';
                ISWCDUPDS.ISWCSORM = 'NOT MERGED';
            else;
                ISWCDUPDS.SOCCSORM = 'NOT MERGED';
            endif;
        endif;


    endif;

    return cTrue;

end-proc;

//------------------------------------------------------------------------------------------
// Procedure name: checkIfChildCompletelyMergedToParent
// Purpose:        checks if child merged to parent
// Returns:        Successful/unsuccessful action
//-------------------------------------------------------------------------------------------

dcl-proc checkIfChildCompletelyMergedToParent;

      dcl-pi *n ind ;
        merged ind;
      end-pi;

      clear isChildWorkKeyMergedToParent;
      clear isChildWorkKeySameAsParent;
      index = 1;

      dow (index < 500 and childWorkKeyArray(index).workKey <> 0);

        merged = *on;
        // check if tbm work key is same as one of the parent work key
        isChildWorkKeySameAsParent = %lookup(childWorkKeyArray(index).workKey :  parentWorkKeyArray(*).workKey) ;

        // if work key not same as one of parent work key, check if they are merged to parent ?
        if (isChildWorkKeySameAsParent = 0);
            if (childWorkKeyArray(index).mergedToWorkKey <> 0); //possible only if child work key is referenced
                // check if the child is merged to a parent key - firstly check if child is merged to one of the parent keys.
                isChildWorkKeyMergedToParent = %lookup(childWorkKeyArray(index).mergedToWorkKey :  parentWorkKeyArray(*).workKey) ;
                if (isChildWorkKeyMergedToParent > 0);
                    ISWCDUPDS.message = %trim(ISWCDUPDS.message)  + 'ISWC TBM Work key ' + %char(childWorkKeyArray(index).workKey) + ' merged to ISWC work key ' + %char(childWorkKeyArray(index).mergedToWorkKey) + '||';
                else;
                     // if not direclty merged to one of the parent keys, check if the child is merged to the parent of parent - parentWorkKeyArray(*).workKeyParentKey!
                   isChildWorkKeyMergedToParent = %lookup(childWorkKeyArray(index).mergedToWorkKey :  parentWorkKeyArray(*).workKeyParentKey) ;
                   if ( isChildWorkKeyMergedToParent > 0 );
                     ISWCDUPDS.message = %trim(ISWCDUPDS.message)  + 'ISWC TBM Work key ' + %char(childWorkKeyArray(index).workKey) + ' and ISWC Work key '+
                     %char(parentWorkKeyArray(isChildWorkKeyMergedToParent).workKey) + ' merged to '+ %char(parentWorkKeyArray(isChildWorkKeyMergedToParent).workKeyParentKey);
                   endif;
                 endif;
            endif;

        else; // if tbm work key and iswc work key are same, it means both iswc's present on same work key.
            if ( check = 'SOC');
                ISWCDUPDS.message = %trim(ISWCDUPDS.message) + 'Society work code and Society work code TBM both present on work key ' + %char(childWorkKeyArray(index).workKey) + '||';
            else;
                ISWCDUPDS.message = %trim(ISWCDUPDS.message) + 'ISWC and ISWC_TBM both present on work key ' + %char(childWorkKeyArray(index).workKey) + '||';
            endif;
        endif;

        if ( isChildWorkKeySameAsParent = 0 and isChildWorkKeyMergedToParent = 0);
            merged = *off ;
            leave;
        endif;

        index = index + 1;

      enddo;

      return cTrue;

end-proc;



//------------------------------------------------------------------------------------------
// Procedure name: checkIfWorkCodesFound
// Purpose:        checks if workkeys present for incoming and target references
// Returns:        Successful/unsuccessful action
//-------------------------------------------------------------------------------------------

dcl-proc checkIfWorkCodesFound;

      dcl-pi *n ind;
        socCodeFound ind;
        socCodeTBMFound ind;
        referenceType char(10);
      end-pi;

      socCodeFound = *on;
      socCodeTBMFound = *on;

      if ( parentWorkKeyArray(firstElement) = *blanks );
        socCodeFound = *off;
        if referenceType = 'ISWC';
            ISWCDUPDS.message = %trim(ISWCDUPDS.message) + ' ISWC not found in ICE ||' ;
        else;
            ISWCDUPDS.message = %trim(ISWCDUPDS.message) + ' Soc. work codes not found in ICE ||' ;
        endif;
      endif;

      if ( childWorkKeyArray(firstElement) = *blanks );
        socCodeTBMFound = *off;
        if referenceType = 'ISWC';
            ISWCDUPDS.message = %trim(ISWCDUPDS.message) + ' ISWC TBM not found in ICE ||' ;
        else;
            ISWCDUPDS.message = %trim(ISWCDUPDS.message) + ' Soc. work codes TBM not found in ICE ||' ;
        endif;
      endif;

      return cTrue;

end-proc;


//---------------------------------------------------------------------
// Procedure name: checkNumberOfActiveWorksonISWC
// Purpose:        checks if target ISWC has more than 1 active work.
//                 If it does, not considered merged.
// Returns:        Successful/unsuccessful action
//---------------------------------------------------------------------

dcl-proc checkNumberOfActiveWorksonISWC;

    dcl-pi *n ind;
        multipleActiveWorksPresent ind;
    end-pi;

    index = 1;
    countOfNonReferencedWorks = 0;
    dow (index < 500 and parentWorkKeyArray(index).workKey <> 0);

        if ( parentWorkKeyArray(index).workIsRef = 'N');
            countOfNonReferencedWorks = countOfNonReferencedWorks + 1;

            if (countOfNonReferencedWorks > 1);
                multipleActiveWorksPresent = *On;
                ISWCDUPDS.message = %trim(ISWCDUPDS.message) + 'Multiple Non-referenced work keys assigned same ISWC - Hence not considered merged||';
                leave;
            endif;

        endif;
        index = index + 1;
    enddo;
    return cTrue;

end-proc;

//---------------------------------------------------------------------------------
// Procedure name: BeginProgram
// Purpose:        Init program
// Returns:        Successful/unsuccessful action
//---------------------------------------------------------------------------------

dcl-proc BeginProgram;
  dcl-pi *n ind end-pi;

  if not DeclareCursors();
    ErrorHandling();
    return cFalse;
  endif;

  return cTrue;

end-proc BeginProgram;


//--------------------------------------------------------------------------------------
// Procedure name: DeclareCursors
// Purpose:        Declares cursors for reading the input file and fetching work keys
// Returns:        Nothing
//---------------------------------------------------------------------------------------
dcl-proc DeclareCursors;
    dcl-pi *n ind end-pi;
//declare cursor for reading the input file
    exec sql declare potiswccur dynamic scroll cursor  for select * from potiswcdup;

// declare cursor for fetching work keys of ISWC
    exec sql declare workKeyISWCCur cursor for
        SELECT
        WRK.WORKKEY,
        WRKISREF,
        COALESCE(WORKKEYM, 0) AS WORKKEYM FROM POTISWCDUP POT JOIN IACWXR WXR
                        ON WXR.WORKREF = :iswcReference AND WXR.WRKREFTYPE = 'ISWC'
                                   JOIN IACWRK WRK ON WXR.WORKKEY = WRK.WORKKEY
                                   LEFT JOIN IACWRM WRM ON WRM.WORKKEYR = WRK.WORKKEY AND WRKRELTYPE = 'MERG'
                                   WHERE SLNUM = :ISWCDUPDS.SLNUM;

 // declare cursor for fetching work keys of SOC Work codes
        exec sql declare workKeySocWorkCodesCur cursor for
        WITH WORKREF_SOCIETY AS (
        SELECT SLNUM,
        SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 5) AS WORKREF ,
        SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) AS SOCIETY ,

        CASE
         WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) = '052' THEN 'ALLTC'
          WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) IN ('023', '055')  THEN 'SWREF'
           WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) IN ('077', '079','089', '090', '110', '116', '112' )  THEN 'IWKEY'
        END
        AS WRKREFTYPE1,

        CASE
            WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) = '052' THEN 'DELTC'
        END
        AS WRKREFTYPE2

        FROM POTISWCDUP ,
        TABLE(SYSTOOLS.SPLIT(:socWorkCodeString,',') ) WHERE SLNUM = :ISWCDUPDS.SLNUM
        AND SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) IN (SELECT SOCCODE FROM IACIAS) )

        SELECT
        WRK.WORKKEY,
        WRKISREF,
        COALESCE(WORKKEYM, 0) AS WORKKEYM FROM WORKREF_SOCIETY WSR JOIN IACWXR WXR

        ON WXR.WORKREF = WSR.WORKREF AND WXR.WRKREFTYPE IN (WSR.WRKREFTYPE1, WSR.WRKREFTYPE2)
                                   JOIN IACWRK WRK
        ON WXR.WORKKEY = WRK.WORKKEY
                                   LEFT JOIN IACWRM WRM
        ON WRM.WORKKEYR = WRK.WORKKEY AND WRKRELTYPE = 'MERG'

        UNION

        SELECT WORKREF , WRKISREF, COALESCE (WORKKEYM, 0)
        FROM WORKREF_SOCIETY JOIN IACWRK ON INT(WORKREF) = WORKKEY
                            LEFT JOIN IACWRM ON WORKKEYR = WORKKEY AND WRKRELTYPE = 'MERG'
        WHERE WRKREFTYPE1 = 'IWKEY';


        exec sql UPDATE thepav.POTISWCDUP SET
        MESSAGE = ' ',
        ISWCSORM = ' ',
        SOCCSORM = ' ',
        IWKEY_ISWC = ' ',
        IWKEYMISWC = ' ' ,
        IWKEYSOCDM = ' ',
        IWKEYSOCD =  ' ' ;

        return cTrue;

end-proc DeclareCursors;



dcl-proc UpdateRecord;

    dcl-pi *n ind end-pi;

        if ( ISWCDUPDS.IWKEY_ISWC = ISWCDUPDS.IWKEYMISWC );
            ISWCDUPDS.ISWCSORM  = 'SAME';
        endif;

        if ( ISWCDUPDS.IWKEYSOCD = ISWCDUPDS.IWKEYSOCDM );
            ISWCDUPDS.SOCCSORM = 'SAME';
        endif;


        exec sql
           UPDATE POTISWCDUP
           SET
               IWKEY_ISWC = :ISWCDUPDS.IWKEY_ISWC ,
               IWKEYMISWC = :ISWCDUPDS.IWKEYMISWC ,
               ISWCSORM   = :ISWCDUPDS.ISWCSORM   ,

               IWKEYSOCD  = :ISWCDUPDS.IWKEYSOCD  ,
               IWKEYSOCDM = :ISWCDUPDS.IWKEYSOCDM ,
               SOCCSORM   = :ISWCDUPDS.SOCCSORM

           WHERE SLNUM = :ISWCDUPDS.SLNUM;

    return cTrue;

end-proc;

//---------------------------------------------------------------------
// Procedure name: Pgm_ErrorHandling
// Purpose:        Process Error handling
// Returns:        Nothing
//---------------------------------------------------------------------
dcl-proc ErrorHandling;

   dump;

end-proc ErrorHandling;

I really dont understand why the same fetch into operation would work so fast in the below program.我真的不明白为什么同样的提取操作在下面的程序中运行得如此之快。 When I check in debug as soon as I press F10, it just moves on to the next line unlike the above one where it just gets stuck on the fetch for like 6 seconds.当我一按 F10 就检查调试时,它只是移动到下一行,这与上面的行不同,它只是停留在提取上大约 6 秒。

**FREE

dcl-ds  parentWorkKeyArray         qualified dim(500);
          //slnum                like(ISWCDUPDS.slnum) inz(0);
          workKey              int(10);
          workIsRef            char(1) inz (*blanks);
          workKeyParentKey     int(10);
end-ds;


dcl-ds ISWCDUPDS                          Extname('POTISWCDUP') qualified;
end-ds;

dcl-s string char(5000);
dcl-s slnum int(5) inz(1);

string = '052|0010018E';

 exec sql declare workKeySocWorkCodesCur cursor for
        WITH WORKREF_SOCIETY AS (
        SELECT SLNUM,
        SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 5) AS WORKREF ,
        SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) AS SOCIETY ,

        CASE
         WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) = '052' THEN 'ALLTC'
          WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) IN ('023', '055')  THEN 'SWREF'
           WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) IN ('077', '079','089', '090', '110', '116', '112' )  THEN 'IWKEY'
        END
        AS WRKREFTYPE1,

        CASE
            WHEN
            SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) = '052' THEN 'DELTC'
        END
        AS WRKREFTYPE2

        FROM POTISWCDUP ,
        TABLE(SYSTOOLS.SPLIT(:string,',') ) WHERE SLNUM = :slnum
        AND SUBSTR (VARCHAR(TRIM(ELEMENT), 20) , 1, 3) IN (SELECT SOCCODE FROM IACIAS) )

        SELECT
        WRK.WORKKEY,
        WRKISREF,
        COALESCE(WORKKEYM, 0) AS WORKKEYM FROM WORKREF_SOCIETY WSR JOIN IACWXR WXR

        ON WXR.WORKREF = WSR.WORKREF AND WXR.WRKREFTYPE IN (WSR.WRKREFTYPE1, WSR.WRKREFTYPE2)
                                   JOIN IACWRK WRK
        ON WXR.WORKKEY = WRK.WORKKEY
                                   LEFT JOIN IACWRM WRM
        ON WRM.WORKKEYR = WRK.WORKKEY AND WRKRELTYPE = 'MERG'

        UNION

        SELECT WORKREF , WRKISREF, COALESCE (WORKKEYM, 0)
        FROM WORKREF_SOCIETY JOIN IACWRK ON INT(WORKREF) = WORKKEY
                            LEFT JOIN IACWRM ON WORKKEYR = WORKKEY AND WRKRELTYPE = 'MERG'
        WHERE WRKREFTYPE1 = 'IWKEY';

        clear parentworkkeyarray;
        exec sql close workKeySocWorkCodesCur;
        exec sql open workKeySocWorkCodesCur;
        exec sql fetch workKeySocWorkCodesCur for 500 rows into :parentWorkKeyArray;
        *inlr = *on;

Before I say anything else, there are two things you must know about embedded SQL. First is the SQL precompiler reads the source in sequential order and does not take into account the execution order of sub-procedures.在我说别的之前,关于嵌入式 SQL,有两件事你必须知道。首先是 SQL 预编译器按顺序读取源代码,不考虑子程序的执行顺序。 The second is that declare cursor is not an executable statement, that is, it is only used by the pre-compiler at compile time, and then commented out.二是declare cursor不是可执行语句,即编译时只供预编译器使用,然后注释掉。 It generates no code, but influences the code generated for other cursor statements.它不生成代码,但会影响为其他 cursor 语句生成的代码。

I'm somewhat surprised this compiles, but not really.我有点惊讶这个编译,但不是真的。 The reason is that you have all your declare cursor statements at the end of the program in a sub-procedure.原因是您在程序末尾的子过程中拥有所有declare cursor语句。 According to the documentation , declare cursor must be physically located in the source before any statement that references it.根据文档declare cursor必须在引用它的任何语句之前物理位于源中。 In your program, all statements that reference the cursors precede their declarations, but the SQL preprocessor does not really understand procedures or program flow, and the declare cursor statement is not executable, so it is not executed at run time, and therefore is not affected by the runtime call order of procedures.在您的程序中,所有引用游标的语句都在其声明之前,但是 SQL 预处理器并不真正理解过程或程序流程,并且declare cursor语句不可执行,因此它不会在运行时执行,因此不受影响按过程的运行时调用顺序。 Since your declares are static and don't rely on procedure parameters, put them up in the beginning of your program with the variable declarations.由于您的声明是 static 并且不依赖过程参数,因此将它们与变量声明一起放在程序的开头。

Also look at the compile listing for your program.还要查看程序的编译列表。 Do the opens of the cursors which reference host variables actually have any lines that indicate they are using those host variables?引用宿主变量的游标的打开实际上是否有任何行表明它们正在使用这些宿主变量? Look at the opens, not the declares.查看打开,而不是声明。 The declares are just commented out with no generated code following them.声明只是被注释掉,后面没有生成代码。

And while you are at it, set option must be the first SQL statement that the precompiler encounters, or it will do nothing.当您使用它时, set option必须是预编译器遇到的第一个 SQL 语句,否则它什么都不做。 So make sure you move that as well.所以一定要移动它。 The structure should be like this:结构应该是这样的:

ctl-opt ....

dcl-* ...

exec sql set option ...

exec sql declare cursor ...

rest of the program

There is one exception to this, and that is when your declare cursor relies on procedure parameters as host variables.有一个例外,那就是当您声明 cursor 依赖过程参数作为主变量时。 In that case I create separate procedures for OpenCursor, FetchCursor, and CloseCursor, these procedures are positioned in that order in the program, and the first thing the OpenCursor procedure does is declare its cursor. This is not so that the declare cursor runs before the open, but instead so that the procedure parameters that are used as host variables in the declare cursor statement are in scope for the declaration.在那种情况下,我为 OpenCursor、FetchCursor 和 CloseCursor 创建了单独的过程,这些过程在程序中按顺序放置,OpenCursor 过程做的第一件事是声明它的 cursor。这并不是说 cursor 在运行之前运行打开,而是使在声明 cursor 语句中用作主变量的过程参数在 scope 中用于声明。 The order of the cursor procedures is important to the precompiler. cursor 过程的顺序对预编译器很重要。 OpenCursor must come first (regardless of the order in which they are called) because the precompiler needs the definition of the cursor so that it can properly generate the code that executes the open cursor , fetch cursor , and close cursor statements. OpenCursor 必须首先出现(无论它们被调用的顺序如何),因为预编译器需要 cursor 的定义,以便它可以正确生成执行open cursorfetch cursorclose cursor语句的代码。

First thing, a difference in statement performance between interactive, via Run SQL Scripts I assume, and an embedded statement is usually because Run SQL Scripts defaults to using a query optimization goal of *FIRSTIO;首先,我假设通过 Run SQL Scripts 交互和嵌入式语句之间的语句性能差异通常是因为 Run SQL Scripts 默认使用查询优化目标 *FIRSTIO; whereas the embedded statement is run with *ALLIO.而嵌入语句使用 *ALLIO 运行。 在此处输入图像描述

Ensure you're testing the statement with *ALLIO, and look at the Explain output for your statement under that optimization goal.确保您正在使用 *ALLIO 测试该语句,并在该优化目标下查看您的语句的 Explain output。

Secondly, take a look at your use of %trim() , you've got a lot of code like so: ISWCDUPDS.message = %trim(ISWCDUPDS.message) +...其次,看看你对%trim()的使用,你有很多这样的代码: ISWCDUPDS.message = %trim(ISWCDUPDS.message) +...

Repeated trimming is very, very, very bad for performance..反复修剪对性能非常非常非常不利..

Ensure that ISWCDUPDS.message is a varchar field or use a temporary varchar to hold the value as you build it up.确保ISWCDUPDS.message是一个 varchar 字段或使用临时 varchar 在构建时保存该值。 Additionally don't use %trim() unless you've got both leading and trailing blanks to worry about.此外,不要使用 %trim() ,除非您需要担心前导空格和尾随空格。 myVarchar +=.... + %trimr(somechar);

If those two tips don't help, then you're going to want to start a DB monitor to see what's going on with the DB itself.如果这两个技巧没有帮助,那么您将需要启动一个 DB 监视器以查看 DB 本身发生了什么。 You might also need to look at doing a Performance Explorer (PEX) to see where the program is spending it's time.您可能还需要查看执行性能资源管理器 (PEX) 以查看程序将时间花在哪里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM