mysql使用游标遍历数据进行批量针对性更新数据,急求mysql大神解答
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql使用游标遍历数据进行批量针对性更新数据,急求mysql大神解答相关的知识,希望对你有一定的参考价值。
我现在有个数据表ud18,里面有图片上的ID,parentid,objname,现在要针对objname的这些号码进行针对性更新,写存储过程进行父子关系转换,做成树形,就是根据objname将父的id值更新到所有子的parentid里去,父项的parentid为0不变,图片上有的,这是我用update ud18 set parentid='1' where objname like '101%' and id <>'1';逐句进行更新的,代码量很大,数据表数据有几千条,现在领导要求用游标遍历数据表进行简便的更新,这些objname是有规律的,数据表里是9位数,比如说父项是1010,那子项就是从101010,101020或者10101010,10101020这样接下去,10101010,10101020就是1010的子项101010的子项,领导跟我说你可以用like匹配前7位数,再依次匹配前5位数,前3位数,然后依次进行更新,我没听懂到底怎么用游标遍历进行更新,求mysql解惑,可加分
急求答案,来个mysql大神给我解答吧,我很急的,我现在还在赚分,可以都给你的,就是用游标遍历数据,然后针对objname进行parentid的数据更新,现在理清了点头绪,就是objname的前三位是前五位的父项,前五位是前七位的父项,然后提取前三位的ID放到前五位的parentid里去,前五位第五位是0的是前五位的父项,前七位第七位是0的话就是前七位的父项,说起来有点绕,大神看图上的objname中的值就知道了,大神仔细帮忙看下,我会一直追加分的
注:我朋友帮我写出了,但是他经常用sql和Oracle的,我拿过来修改了一下,我自己也是初学者,麻烦大神帮我看下逻辑和语法,语法应该还有错误,但是一直都做到2点多我实在太困了,麻烦大神帮我检查一下,我明天急用,谢谢了
CREATE DEFINER=`root`@`localhost` PROCEDURE `P_updateUd18`(`Param` int(11))
BEGIN
declare Rcount,i,j,k,Rparentid,myId int(11) default 0;
declare Robjname,Robjname23,Robjname45,Robjname67,Robjname89 varchar(9) default "";
select count(id) into Rcount from ud18;
repeat
select id,objname into myId,Robjname from ud18 order by id limit i,1;
set Robjname23=SUBSTRING(Robjname,2,2);
set Robjname45=SUBSTRING(Robjname,4,2);
set Robjname67=SUBSTRING(Robjname,6,2);
set Robjname89=SUBSTRING(Robjname,8,2);
if Robjname89>0 then
set @sql=concat("select id into @abc from ud18 where objname like '",left(Robjname,7),"00","'");
prepare stmt from @sql;
EXECUTE stmt;
set Rparentid=@abc;
update ud18 set parentid=Rparentid where id=myId;
elseif Robjname67>0 then
set @sql=concat("select id into @abc from ud18 where objname like '",left(Robjname,5),"0000","'");
prepare stmt from @sql;
EXECUTE stmt;
set Rparentid=@abc;
update ud18 set parentid=Rparentid where id=myId;
elseif Robjname45>0 then
set @sql=concat("select id into @abc from ud18 where objname like '",left(Robjname,3),"000000","'");
prepare stmt from @sql;
EXECUTE stmt;
set Rparentid=@abc;
update ud18 set parentid=Rparentid where id=myId;
elseif Robjname23>0 then
-- set @sql=concat("select id into @abc from ud18 where objname like '",left(Robjname,1),"00000000","'");
-- prepare stmt from @sql;
-- EXECUTE stmt;
-- set Rparentid=@abc;
update ud18 set parentid=0 where id=myId;
else
set j=0;
end if;
set i=i+1;
until i>Rcount end repeat;
END; 参考技术A 1、游标是数据库的一个缓冲区,游标标识这个缓冲区的地址。这个缓冲区的访问是连续的,也可以理解为数据存放是连续的,所以使用游标访问速度快,不需要离散式的寻址,一个接着一个的处理数据即可,省去寻址时间。
2、游标使用的时候,需要设置,也就是把需要处理的数据放入缓冲区中,也就是用条件语句选取数据集,设置好后,游标自然指向第一个数据项的地址,可以用fetch指令进行取数据操作。对于你来说,就是将用like匹配的七位、五位、三位放入缓冲区。游标使用语法,就不多说了,网上多的是。
3、对于父亲节点的描述,感觉没有描述清楚。根据你的描述,不必进行三位、五位、七位的遍历,直接根据前三位就把所有匹配的数据项都赋给同一个parentid了。但是根据你领导所说,好像不是这样,也就是你说的转换关系与你领导意图不同,你领导的意图是同一个儿子的parentid指向同一个父亲,也就是父亲节点的ID。如果这样的话,需要从叶子节点向上遍历,也就是你领导说的先七位,再五位,再三位。
4、写个例子,可以参考。参数可以依次是七位、五位、三位。
/*建立 存储过程 create */
CREATE PROCEDURE useCursor( parent vachar(9))
BEGIN
/*局部变量的定义 declare*/
declare ID varchar(20) default '' ;
declare temp ID (255) default '' ;
declare parentVchar varchar(9);
set parentVchar=parent;
declare cur1 CURSOR FOR SELECT id FROM tud18 where parented like parentVchar order by id;
/*开游标*/
OPEN cur1;
/*游标向下走一步*/
FETCH cur1 INTO ID;
WHILE (tempID is not null) DO
Update tud18 set parentid = ID ;
/*游标向下走一步*/
FETCH cur1 INTO tempID;
END WHILE;
CLOSE cur1;
END;//追问
我找我朋友帮我大概写了下,我补充的问题,麻烦你帮我看下吧,看下语法和逻辑有没错误,我明天赶着要,谢谢了
追答1、oracle语法与mysql语法不同,慎用。
2、你需要环境调试,可以先建一个中间表,把数据导入后,试试。
3、你发的这个程序,感觉有些繁琐,也就是循环中,每次都要做一个select,背离了游标的好处,其实不必的,只要select一次,排好序,就可以依次操作了。
4、不建议两个父节点同时操作,容易出现混乱情况,可以一级一级节点操作,从叶子节点开始向上。而程序中是按照每个循环两层节点情况。如果出现节点层次是奇数,就会出现混乱情况。
我是mysql新手,你说的这些我能看懂,但是我不知道如何去写,你能不能写个类似的例子让我看看,谢谢了
参考技术B DELIMITER $$CREATE DEFINER=`root`@`%` PROCEDURE `P_UPDATEud18`(i_Param bigint)
label_proc:
BEGIN
declare v_pid bigint;
declare v_i bigint;
declare v_pre bigint;
declare v_ar bigint;
declare v_ae bigint;
declare OE CURSOR FOR select left(objname,7) from ud18;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_departments=1;
open OE ;
REPEAT
FETCH OE INTO v_i;
select id into v_pid from ud18 where substring(v_i,7,1)=0;
select id into v_ae from ud18 where substring(v_i,5,1)=0;
select left(v_i,3) into v_pre;
select left(v_i,5) into v_ar;
update ud18 set parentid=v_ae where v_pre=left(objname,3);
update ud18 set parentid=v_pid where v_ar=left(objname,5);
UNTIL no_more_departments
END REPEAT;
close OE;
END追问
一运行就报这个错,这是什么情况?
少了一句:
declare no_more_departments int default 0;
这句就加在declare v_pid bigint;的上面
以上是关于mysql使用游标遍历数据进行批量针对性更新数据,急求mysql大神解答的主要内容,如果未能解决你的问题,请参考以下文章