DB2/400 打开游标的替代方法
DB2/400 Alternative to Opening a Cursor
我是 运行 DB2 for i,V7R2 TR3。
有人告诉我打开游标会产生大量开销,应尽可能避免。根据我的阅读,使用 EXECUTE INTO var1 USING var2
是一种替代方法,但我无法使其正常工作。我收到 SQL0104 error.
这是我的存储过程:
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 ;
它定义了三个变量:
IN ITEM CHAR(20) CCSID 37 DEFAULT '' ,
IN TYPE INT DEFAULT 1 ,
INOUT BASEITEM CHAR(20) DEFAULT ''
当我有 EXECUTE INTO...
时,这不会编译,如果我使用 EXECUTE USING...
,它会编译,但 BASEITEM
最终为空,IF
语句解析为 true .
我尝试按照 EXECUTE documentation and apparently the INTO
can only work for CALL
or VALUES INTO
statements. So I then tried to follow the VALUES INTO 文档进行操作,但不知道如何使用它进行查询。
注意*:我想最终更改串联变量以使用参数标记,但接下来我会担心这个。
我认为我应该 post 使用 table:
MYLIB.MYTABLE
Column |Prefix|SEQ1|SEQ2|
Row 1 |aaa | 1| 3|
Row 2 |aab | 1| 3|
Row 3 |aabd | 2| 4|
我实际上是在传递一个字符串,然后从该字符串中删除最长的前缀。然后我返回了新字符串。 SEQ1
只是前缀的类型(1 或 2),SEQ2 是前缀的长度。
EXECUTE
只能用于DML语句,不能用于查询,所以除了声明动态游标实在是别无选择。话虽如此,没有 "overhead in opening a cursor",就像以任何其他方式执行查询一样,因为对于任何查询,如果不是显式地,仍然会隐式地创建和打开游标。
游标的效率低于 set-based 操作,例如什么时候,而不是做类似 INSERT INTO table1 SELECT something FROM table2 WHERE...
的事情,而是在 table2
上打开一个游标,然后在循环中将行一个接一个地插入到 table1
中。在这种情况下,效率低下是由于执行单行插入(或更新)而不是多行更新,而不是游标本身,这与声明 "opening a cursor provides a lot of overhead" 完全不同。
因为在你的情况下你只能获取一条记录,所以这个循环与设置参数不适用。
您遇到错误是因为 EXECUTE stmt INTO
没有按照您认为的方式工作。
真正的问题是您试图在不需要时使用动态 SQL。请改用静态。
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 ;
我是 运行 DB2 for i,V7R2 TR3。
有人告诉我打开游标会产生大量开销,应尽可能避免。根据我的阅读,使用 EXECUTE INTO var1 USING var2
是一种替代方法,但我无法使其正常工作。我收到 SQL0104 error.
这是我的存储过程:
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 ;
它定义了三个变量:
IN ITEM CHAR(20) CCSID 37 DEFAULT '' ,
IN TYPE INT DEFAULT 1 ,
INOUT BASEITEM CHAR(20) DEFAULT ''
当我有 EXECUTE INTO...
时,这不会编译,如果我使用 EXECUTE USING...
,它会编译,但 BASEITEM
最终为空,IF
语句解析为 true .
我尝试按照 EXECUTE documentation and apparently the INTO
can only work for CALL
or VALUES INTO
statements. So I then tried to follow the VALUES INTO 文档进行操作,但不知道如何使用它进行查询。
注意*:我想最终更改串联变量以使用参数标记,但接下来我会担心这个。
我认为我应该 post 使用 table: MYLIB.MYTABLE
Column |Prefix|SEQ1|SEQ2|
Row 1 |aaa | 1| 3|
Row 2 |aab | 1| 3|
Row 3 |aabd | 2| 4|
我实际上是在传递一个字符串,然后从该字符串中删除最长的前缀。然后我返回了新字符串。 SEQ1
只是前缀的类型(1 或 2),SEQ2 是前缀的长度。
EXECUTE
只能用于DML语句,不能用于查询,所以除了声明动态游标实在是别无选择。话虽如此,没有 "overhead in opening a cursor",就像以任何其他方式执行查询一样,因为对于任何查询,如果不是显式地,仍然会隐式地创建和打开游标。
游标的效率低于 set-based 操作,例如什么时候,而不是做类似 INSERT INTO table1 SELECT something FROM table2 WHERE...
的事情,而是在 table2
上打开一个游标,然后在循环中将行一个接一个地插入到 table1
中。在这种情况下,效率低下是由于执行单行插入(或更新)而不是多行更新,而不是游标本身,这与声明 "opening a cursor provides a lot of overhead" 完全不同。
因为在你的情况下你只能获取一条记录,所以这个循环与设置参数不适用。
您遇到错误是因为 EXECUTE stmt INTO
没有按照您认为的方式工作。
真正的问题是您试图在不需要时使用动态 SQL。请改用静态。
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 ;