DB2/400 Alternative to Opening a Cursor

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-13 01:08:09

问题


I'm running DB2 for i, V7R2 TR3.

I was told opening a cursor provides a lot of overhead and should be avoided whenever possible. From what I've read, using EXECUTE INTO var1 USING var2 is an alternative, but I can't get it working. I am getting a SQL0104 error.

This is my Stored Procedure:

BEGIN 
DECLARE STMT1 VARCHAR ( 500 ) ;     

SET STMT1 =     'SELECT SUBSTR (''' || TRIM(ITEM) || ''' , ( LENGTH ( TRIM ( PREFIX ) ) + 1 ) , ( 20 - LENGTH ( TRIM ( PREFIX ) ) ) ) ' ||
                'FROM   MYLIB.MYTABLE ' ||
                'WHERE  PREFIX = SUBSTR(''' || TRIM(ITEM) || ''', 0,LENGTH ( TRIM ( PREFIX ) ) + 1 ) ' ||
                'AND    SEQ1 = ' || TYPE || ' ' ||
                'ORDER BY   LENGTH ( TRIM ( PREFIX) ) DESC , TRIM (PREFIX) DESC ' ||
                'FETCH FIRST 1 ROWS ONLY ';

PREPARE S1 FROM STMT1; 
EXECUTE S1 INTO BASEITEM;

--OPEN C1 ; 
--  FETCH C1 INTO BASEITEM ; 
--CLOSE C1 ; 

IF(TRIM(BASEITEM) = '') THEN
    SET BASEITEM = ITEM;
END IF;
END  ; 

It has three variables defined as such:

IN ITEM CHAR(20) CCSID 37 DEFAULT  ''  , 
IN TYPE INT DEFAULT  1  , 
INOUT BASEITEM CHAR(20) DEFAULT  '' 

When I have EXECUTE INTO... this will not compile, if I use EXECUTE USING... it will compile but BASEITEM ends up being blank and the IF statements resolves as true.

I've tried following the the EXECUTE documentation and apparently the INTO can only work for CALL or VALUES INTO statements. So I then tried to follow the VALUES INTO documentation, but can't figure out how to use a query with it.

Note*: I'd like to eventually change the concatenated variables to use parameter markers, but I was going to worry about that next.

I figured I should post the table being used: MYLIB.MYTABLE

Column |Prefix|SEQ1|SEQ2|
Row 1  |aaa   |   1|   3|
Row 2  |aab   |   1|   3|
Row 3  |aabd  |   2|   4|

I'm essentially passing in a string and then removing the longest prefix from the string. Then I returned the new string. SEQ1 is just the type of prefix (either 1 or 2), SEQ2 is the length of the prefix.


回答1:


EXECUTE can only be used for DML statements, not for queries, so there is really no alternative to declaring a dynamic cursor. Having said that, there is no "overhead in opening a cursor", no more than in executing a query in any other manner, because for any query a cursor will still be created and opened implicitly, if not explicitly.

Cursors are less efficient than set-based operations, e.g. when, instead of doing something like INSERT INTO table1 SELECT something FROM table2 WHERE... you open a cursor over table2 and insert rows into table1 one by one in a loop. Inefficiency in such case arises from performing single row inserts (or updates) vs. multirow updates, not from the cursor itself, and that is completely different from stating that "opening a cursor provides a lot of overhead".

Since in your case you only fetch one record anyway, this loop vs. set argument does not apply.




回答2:


You're getting an error because EXECUTE stmt INTO doesn't work the way you think it does.

The real problem is that you're trying to use dynamic SQL when you don't need to be. Use static instead.

BEGIN 

  SELECT SUBSTR (TRIM(ITEM), ( LENGTH ( TRIM ( PREFIX ) ) + 1 ) , ( 20 - LENGTH ( TRIM ( PREFIX ) ) ) )
    INTO BASEITEM
    FROM   MYLIB.MYTABLE 
   WHERE  PREFIX = SUBSTR(TRIM(ITEM), 0,LENGTH ( TRIM ( PREFIX ) ) + 1 )
          AND    SEQ1 = TYPE
   ORDER BY   LENGTH ( TRIM ( PREFIX) ) DESC , TRIM (PREFIX) DESC
   FETCH FIRST 1 ROWS ONLY;

IF(TRIM(BASEITEM) = '') THEN
    SET BASEITEM = ITEM;
END IF;
END  ;


来源:https://stackoverflow.com/questions/34661872/db2-400-alternative-to-opening-a-cursor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!