2016-01-06 61 views
1

我與DB2工作我在IBM i V7R2 TR3多繼續在DB2處理程序爲我存儲過程

我想寫包含兩個SELECT語句的存儲過程。其中第一個用遊標循環,第二個用於循環。如果記錄從第二個(內部)SELECT返回,那麼我需要跳出循環,否則繼續。我見過Exception Handlers的例子,但是當我試圖實現它們時,我會在第一次迭代時被拋出循環。我爲什麼Exception Handlers不適用於我的假設是因爲我將Exception Handler設置爲全局級別,並且第二次(內部)SELECT在第一次迭代期間返回零結果(它將主要返回零行),異常處理程序是觸發器,我擺脫了存儲過程而不是循環。

如何在單個存儲過程中爲特定SQL語句設置多個Exception Handlers?我已閱讀了DB2中的複合語句,但無法弄清楚如何指定Exception Handler適用於哪種語句。

https://www-01.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/com.ibm.db2z11.doc.sqlref/src/tpc/db2z_compoundstatement4nativesqlpl.html

我已經嘗試了一些替代方法來Exception Handlers這正是我現在有。我並沒有死在Exception Handlers上,但很高興知道如何使用多個Exception Handlers

這是我的存儲參考過程(具有改變的lib /表),如果有幫助:

DECLARE EOF1 INT DEFAULT 0 ; 
DECLARE EOF2 INT DEFAULT 0 ; 
DECLARE CURMATCH CHAR (20) DEFAULT '' ; 
DECLARE CURPREFIX CHAR (20) DEFAULT '' ; 
DECLARE PREFIXES CURSOR FOR 
    SELECT TRIM (PREFIX) || '%' 
    FROM MYLIB/PREFIXTABLE 
    ORDER BY LENGTH (TRIM (PREFIXCOL)) DESC , TRIM (PREFIXCOL) DESC ; 



OPEN PREFIXES ; 
WHILE EOF1 = 0 DO 

    FETCH FROM PREFIXES INTO CURPREFIX ; 

    IF TRIM (CURPREFIX) = '' THEN 
     SET EOF1 = 1 ; 
    END IF ; 

    SELECT DISTINCT BASEITEM , 
     SUBSTR (BASEITEM , 
     (LENGTH (TRIM (CURPREFIX)) + 1) , (20 - LENGTH (TRIM (CURPREFIX))) 
    ) INTO CURMATCH 
    FROM MYLIB/ITEMTABLE 
    WHERE BASEITEM = ITEM 
    AND CASE 
      WHEN BASEITEM LIKE '' || CURPREFIX || '' THEN 1 
      ELSE 0 
     END = 1 ;   

    IF (TRIM (CURMATCH) <> '') THEN 
     SET BASEITEM = TRIM (CURMATCH) ; 
     SET EOF2 = 1 ; 
    END IF ; 
    IF EOF2 <> 0 THEN 
     SET EOF1 = 1 ; 
    END IF ; 

END WHILE ; 
CLOSE PREFIXES ; 

IF(EOF2 = 0) THEN 
    SET BASEITEM = 'NOT FOUND'; 
END IF; 

該存儲的過程被設置爲接受2個參數定義爲:

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

我忘了提及上面的代碼似乎造成了無限循環。當我打電話給程序時,它只是繼續運行而不停止。在殺死它之前,我會讓它運行長達10分鐘,而且我認爲這些表格中的記錄數量不會太長。

+1

我看到你有你的答案......但只是想說,SQL不是RPG。你應該考慮設置操作,而不是使用遊標逐行。我的座右銘(對於那些剛接觸SQL的人),如果你使用遊標,你做錯了什麼。是的,有時你必須使用遊標,但是當RPG(或其他程序)程序員不需要時使用遊標太容易了。我建議在代碼,輸入和期望輸出以及表格示例中發佈一個新問題,並查看是否有人能夠向您展示基於集合的解決方案。 – Charles

+0

我與查爾斯 - 你可以在一個聲明中做這個(和_faster_)。哦,你有一個小的SQL注入漏洞,因爲你要連接字符串進行搜索。由於它們只能得到20個字符,所以不是非常可利用的,但你仍然應該使用參數標記。 –

+1

我已經將存儲過程更改了很多,同時將建議考慮在內。無論哪種方式,我已經發布了一個關於消除使用遊標的新問題,如您在這裏建議的http:// stackoverflow。com/questions/34661872/db2-400-alternative-to-opening-a-cursor –

回答

3

信號(異常)處理程序對聲明它們的塊是本地的。過程體是最外面的塊,但是你可以定義嵌套塊。既然你沒有張貼您的代碼(一個與信號處理器),我不能確切地告訴你如何修改它,但一般它會是這個樣子:

CREATE PROCEDURE yourproc 
... 
BEGIN 
    DECLARE prefixes CURSOR FOR ... 
    OPEN PREFIXES ; 
    WHILE EOF1 = 0 DO 
    FETCH FROM PREFIXES INTO CURPREFIX ; 
    BEGIN -- inner block 
     DECLARE CONTINUE HANDLER FOR ... 
     ... -- do whatever 
    END; -- inner block 
    END WHILE ; 
    ... 
END -- procedure 

基本上,你的包語句,您希望在BEGIN ... END塊中處理其信號,並在該塊內聲明處理程序。

+0

感謝您的回答,我不得不切換一些其他(大多數不相關)的東西,讓它在我的特定用例中工作,但這正是需要的。 –