2017-02-14 81 views
-1

我有下面的代碼:無錯DB2更新不執行

BEGIN 
DECLARE cmd VARCHAR(1024); DECLARE attr CHAR(10); 
DECLARE attr2 CHAR(10); 
DECLARE at_end INTEGER DEFAULT 0; 
DECLARE not_found CONDITION FOR SQLSTATE '02000'; 
DECLARE updstr1 VARCHAR(1024); 
DECLARE updstr2 VARCHAR(1024); 


DECLARE c1 CURSOR FOR SELECT cmd, attr, attr2 
         FROM commandtbl2; 

DECLARE CONTINUE HANDLER FOR not_found SET at_end = 1; 

SET updstr1 = 'update commandtbl3 t2 set t2.XXXX = attr where t2.cmd=cmd'; 
SET updstr2 = 'update commandtbl3 t2 set t2.XXXX= attr2 where t2.cmd=cmd'; 
OPEN c1; 

ins_loop: LOOP 

    FETCH c1 INTO cmd, attr, attr2; 

    IF at_end = 1 THEN 
    LEAVE ins_loop; 
    ELSEIF cmd != '' THEN 
    ITERATE ins_loop; 
    END IF; 

    set updstr1= REPLACE(updstr1,'XXXX','attr'); 
    set updstr2= REPLACE(updstr2,'XXXX','attr2'); 

    EXECUTE IMMEDIATE updstr1; 
    EXECUTE IMMEDIATE updstr2; 


END LOOP; 

CLOSE c1; 
[email protected] 

這一切都運行,但是當我檢查commandtbl3什麼也沒有更新。所有的值都是NULL,但應該被替換。這兩個表中有7行,5個具有匹配的cmd值,所以這5行應該更新。

我不確定替換是不是工作或執行即時。

隨着調試我發現,updstr1和2變量在替換後是空的......但爲什麼?

你能幫我嗎? 謝謝, TheVagabond

如這裏請求是commandtbl3和2的定義:

CREATE TABLE "TEST"."COMMANDTBL3" (
    "ID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 NO CYCLE CACHE 2 NO ORDER), 
    "CMD" VARCHAR(1024 OCTETS) NOT NULL, 
    "ATTR" CHAR(10 OCTETS), 
    "ATTR2" CHAR(10 OCTETS), 
    CONSTRAINT "CC1455789123996" PRIMARY KEY 
    ("ID") 
) 

CREATE TABLE "TEST"."COMMANDTBL2" (
    "ID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 NO CYCLE CACHE 2 NO ORDER), 
    "CMD" VARCHAR(1024 OCTETS) NOT NULL, 
    "ATTR" CHAR(10 OCTETS), 
    "ATTR2" CHAR(10 OCTETS), 
    CONSTRAINT "CC1455789123996" PRIMARY KEY 
    ("ID") 
) 

COmmandtbl3具有CMD等於除2行commandtbl2(7行總數)和attR和attR2是NMULL在commandtbl3 。我要被寫入通過更新commandtbl3與替換的命令,這樣我就可以有佔位符commandtbl2 ATTR和attR2值XXXX

這裏是工作代碼:

如果有人在這裏有相同的概率是工作代碼,即使從開始的(while循環現在等)改變:

BEGIN 
DECLARE EOF INTEGER DEFAULT 0; 
DECLARE cmd VARCHAR(1024); DECLARE attr CHAR(10); 
DECLARE attr2 CHAR(10); 
DECLARE not_found CONDITION FOR SQLSTATE '02000'; 
DECLARE updstr1 VARCHAR(1024); 
DECLARE updstr2 VARCHAR(1024); 
DECLARE stmt1 STATEMENT; 
DECLARE stmt2 STATEMENT; 

DECLARE c1 CURSOR FOR SELECT cmd, attr, attr2 
        FROM commandtbl2 order by cmd; 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET EOF = 1; 

SET updstr1 = 'update commandtbl3 t2 set t2.XXXX = ? where t2.cmd= ?'; 
SET updstr2 = 'update commandtbl3 t2 set t2.XXXX= ? where t2.cmd= ?'; 
set updstr1= REPLACE(updstr1,'XXXX','attr'); 
set updstr2= REPLACE(updstr2,'XXXX','attr2'); 
insert into temptbl(text1,text2) values(updstr1,updstr2); 

prepare stmt1 from updstr1; 
prepare stmt2 from updstr2; 

OPEN c1; 


WHILE EOF = 0 DO 

FETCH from c1 INTO cmd, attr, attr2; 
EXECUTE stmt1 using attr, cmd; 
EXECUTE stmt2 using attr2, cmd; 

END WHILE; 

CLOSE c1; 
[email protected] 
+0

檢查如何在動態的語句中使用的參數再次手動。提示:將會有一個'PREPARE'語句,'EXECUTE'將有'USING'子句。 – mustaccio

+0

我知道,從其他編碼語言嵌入SQL語句準備,我需要的是隻使用SQL的時候也是一樣,我沒有一個參數標記我剛剛替換字符串。 – Thevagabond

+0

您確實希望在後面的''cmd'其中t2.cmd = cmd'由您提取到前面,一個變量來代替神奇,不是嗎?不會發生。 – mustaccio

回答

1

您的代碼中有幾個邏輯錯誤。

  1. 在你的循環:

    IF at_end = 1 THEN 
        LEAVE ins_loop; 
    ELSEIF cmd != '' THEN 
        ITERATE ins_loop; 
    END IF; 
    

    ELSEIF語句告訴DB2,如果cmd(從commandtbl2)是什麼一個空字符串,它應該跳過本次迭代的剩餘步驟(即它什麼也不做,只是跳回到循環開始處的FETCH聲明)。

    這可能是你沒有看到任何事情發生的原因。

  2. 正如@mustaccio在上述註釋中提到的那樣,您似乎認爲DB2會在執行EXECUTE IMMEDIATE語句時奇蹟般地用它們的值替換變量。您的發言:

    update commandtbl3 t2 set t2.XXXX = attr where t2.cmd=cmd 
    

    您的代碼將取代XXXX,但可以肯定的看起來像你假設= attr=cmd也將與獲得的FETCH語句設置的值來代替。不是這種情況。

    見這個例子:

    DECLARE GLOBAL TEMPORARY TABLE t1 (c1 int) 
    ON COMMIT PRESERVE ROWS WITH REPLACE 
    @ 
    
    BEGIN 
        DECLARE v1 INT; 
        DECLARE vSQL VARCHAR(128); 
    
        SET vSQL = 'INSERT INTO SESSION.T1 values (v1)'; 
        SET v1 = 12; 
    
        EXECUTE IMMEDIATE vSQL; 
    END 
    @ 
    

    當數據庫達到EXECUTE IMMEDIATE聲明,它不會隨着V1在運行時的值替換V1。它會執行確切的語句INSERT INTO SESSION.T1 values (v1)。這當然會,失敗,因爲V1並不意味着什麼到數據庫。

    在你的情況下,EXECUTE IMMEDIATE語句將不會失敗因爲attrcmd做意味着什麼到數據庫中 - 它們在表commandtbl3列名。因此,執行您的更新語句將(後REPLACE語句):

    update commandtbl3 t2 set t2.attr = attr where t2.cmd=cmd 
    update commandtbl3 t2 set t2.attr2 = attr2 where t2.cmd=cmd 
    

    這些基本上是空操作 - 樣UPDATE T1 SET C1 = C1 WHERE C2 = C2

    這就是爲什麼你不應該使用聲明相同的名稱爲您的數據庫列變量一個很好的例子。它增加了混淆並可以隱藏邏輯錯誤。