2017-02-14 36 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

    这就是为什么你不应该使用声明相同的名称为您的数据库列变量一个很好的例子。它增加了混淆并可以隐藏逻辑错误。