我有以下代码:
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;
END@
这一切都运行没有错误但是当我检查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等于commandtbl2,除了2行(总共7行),attr和attr2是commandtbl3中的NMULL。我希望commandtbl2 attr和attr2的值通过更新写入commandtbl3并替换为命令,这样我就可以拥有占位符XXXX
这是工作代码:
如果某人有相同的概率,那么就是工作代码,即使从起始代码改变了(现在循环,等等):
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;
END@
答案 0 :(得分:1)
您的代码中存在一些逻辑错误。
在你的循环中:
IF at_end = 1 THEN
LEAVE ins_loop;
ELSEIF cmd != '' THEN
ITERATE ins_loop;
END IF;
ELSEIF
语句告诉DB2,如果cmd
(来自commandtbl2
)是但是是一个空字符串,它应该跳过剩余的步骤这个循环的迭代(即它什么也不做,只是在循环开始时跳回FETCH
语句。)
这可能是你没有看到任何事情发生的原因。
正如@mustaccio在上面的评论中所提到的,看起来你假设当你执行EXECUTE IMMEDIATE
语句时,DB2将神奇地用变量替换变量。你的陈述:
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
语句不会失败,因为attr
和cmd
对数据库有意义 - 它们是列中的列名表格1}}。所以你执行的更新语句将是(在REPLACE语句之后):
commandtbl3
这些基本上是无操作的 - 比如update commandtbl3 t2 set t2.attr = attr where t2.cmd=cmd
update commandtbl3 t2 set t2.attr2 = attr2 where t2.cmd=cmd
。
这是一个很好的例子,说明为什么不应该使用与数据库中的列相同的名称来声明变量。它会增加混淆并隐藏逻辑错误。