问题
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