简体   繁体   中英

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;

is performing very slowly. It tales about 6 seconds to execute each time. 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. 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.

**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. 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. It generates no code, but influences the code generated for other cursor statements.

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. According to the documentation , declare cursor must be physically located in the source before any statement that references it. 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. 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.

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. 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. 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. The order of the cursor procedures is important to the precompiler. 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.

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; whereas the embedded statement is run with *ALLIO. 在此处输入图像描述

Ensure you're testing the statement with *ALLIO, and look at the Explain output for your statement under that optimization goal.

Secondly, take a look at your use of %trim() , you've got a lot of code like so: 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. Additionally don't use %trim() unless you've got both leading and trailing blanks to worry about. 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. You might also need to look at doing a Performance Explorer (PEX) to see where the program is spending it's time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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