db2 在rpgle中将游标读取到数组中时性能降低

snvhrwxg  于 2022-11-07  发布在  DB2
关注(0)|答案(2)|浏览(212)

我有一个相对简单的rpg程序,其中exec sql workKeySocWorkCodesCur for 500 rows into :childWorkKeyArray;
执行得非常慢。每次执行大约需要6秒。我不明白的是,当我以交互方式运行此查询时,或者当我在仅包含此语句的单独RPG中测试此语句时(通过替换主机变量值),它似乎在不到一秒的时间内完成。那么,此程序中的什么差异可能导致它变慢呢?


**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;

我真的不明白为什么同样的获取操作在下面的程序中会工作得这么快。当我按下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;
dgiusagp

dgiusagp1#

在我说别的之前,有两件事你必须知道关于嵌入式SQL,第一是SQL预编译器按顺序读取源代码,不考虑子过程的执行顺序,第二是declare cursor不是一个可执行语句,也就是说,它只在编译时被预编译器使用,然后被注解掉,它不生成代码。但会影响为其他游标语句生成的代码。
我对它的编译有些惊讶,但并不真的惊讶。原因是所有的declare cursor语句都在程序的最后一个子过程中。根据documentationdeclare cursor在源代码中必须位于引用它的任何语句之前。在程序中,所有引用游标的语句都在它们的声明之前。但是SQL预处理器并不真正理解过程或程序流,而且declare cursor语句是不可执行的,因此它不在运行时执行,因此不受过程的运行时调用顺序的影响。把它们放在程序的开头和变量声明一起。
还要查看程序的编译列表。引用主机变量的游标的打开是否实际上有任何行指示它们正在使用这些主机变量?请查看打开,而不是声明。声明只是被注解掉了,后面没有生成代码。
在此过程中,set option必须是预编译器遇到的第一个SQL语句,否则它将不执行任何操作。因此,请确保您也移动了它。结构应该是这样的:

ctl-opt ....

dcl-* ...

exec sql set option ...

exec sql declare cursor ...

rest of the program

有一个例外,那就是当您的声明游标依赖于过程参数作为宿主变量时。在这种情况下,我为OpenCursor、FetchCursor和CloseCursor创建了单独的过程,这些过程在程序中按此顺序放置,OpenCursor过程所做的第一件事是声明它的游标。这并不是说声明游标在打开游标之前运行,而是使在declare cursor语句中用作主机变量的过程参数处于声明的作用域中。游标过程的顺序对预编译器很重要。OpenCursor必须排在第一位(无论调用顺序如何)因为预编译器需要游标的定义,以便能够正确地生成执行open cursorfetch cursorclose cursor语句的代码。

cld4siwp

cld4siwp2#

首先,通过RunSQLScripts的交互式语句和嵌入式语句之间的语句性能差异通常是因为RunSQLScripts默认使用 *FIRSTIO的查询优化目标;而嵌入式语句则使用 *ALLIO. x1c 0d1x运行
确保使用 *ALLIO测试语句,并查看该优化目标下语句的Explain输出。
第二,看看你对%trim()的使用,你有很多这样的代码:ISWCDUPDS.message = %trim(ISWCDUPDS.message) + ...
重复修剪对性能非常非常非常不好。
确保ISWCDUPDS.message是一个varchar字段,或者使用临时的varchar来保存值。另外,不要使用%trim(),除非你需要担心前导和尾随空格。myVarchar += .... + %trimr(somechar);
如果这两个提示没有帮助,那么您将需要启动一个DB监视器来查看DB本身的情况。您可能还需要考虑执行一个性能资源管理器(PEX)来查看程序在哪里花费了时间。

相关问题