关于mysql写触发器中运用游标的问题。

来源:互联网 发布:回到明朝当王爷网络剧 编辑:程序博客网 时间:2024/04/28 01:28


Mysql中游标的用法现在提供的还很特别,虽然使用起来没有PL/SQL那么顺手,不过使用上大致上还是一样,本文将详细介绍一下,需要了解的朋友可以参考下

首先定义游标(不论声明变量还是游标还是其他的什么都要在你执行任何操作的前面,不然会报错的)

declare cur_count cursor for select seqname, value from sys_sequence;

 (这里如果用到变量的话就直接 在数据库查,因为这里是在声明,你的任何变量现在都是没有值得)

使用游标
open cur_count ;
fetch获得数据 给_seqname, _value
fetch cursor into _seqname, _value;
关闭游标
close cur_count ;
不过这都是针对cursor的操作而已,和PL/SQL没有什么区别吧,不过光是了解到这个是根本不足以写出Mysql的fetch过程的,还要了解其他的更深入的知识,我们才能真正的写出好的游标使用的procedure
首先fetch离不开循环语句,那么先了解一下循环吧。
我一般使用Loop和while觉得比较清楚,而且代码简单。


这里使用Loop为例

fetchSeqLoop:Loop fetch cursor into _seqname, _value; end Loop; 



现在是死循环,还没有退出的条件,那么在这里和oracle有区别,Oracle的PL/SQL的指针有个隐性变量%notfound,Mysql是通过一个Error handler的声明来进行判断的,
declare continue handler for Not found (do some action);
在Mysql里当游标遍历溢出时,会出现一个预定义的NOT FOUND的Error,我们处理这个Error并定义一个continue的handler就可以叻,关于Mysql Error handler可以查询Mysql手册定义一个flag,在NOT FOUND,标示Flag,在Loop里以这个flag为结束循环的判断就可以叻。

declare fetchSeqOk boolean; ## define the flag for loop judgement declare _seqname varchar(50); ## define the varient for store the data declare _value bigint(20); declare fetchSeqCursor cursor for select seqname, value from sys_sequence;## define the cursor declare continue handler for NOT FOUND set fetchSeqOk = true; ## define the continue handler for not found flag set fetchSeqOk = false; open fetchSeqCursor; fetchSeqLoop:Loop if fetchSeqOk then leave fetchSeqLoop; else fetch cursor into _seqname, _value; select _seqname, _value; end if; end Loop; close fetchSeqCursor; 

这就是一个完整的过程叻,那么会思考的人一般在这里都会思考,如果是这样的话,怎样做嵌套的游标循环叻,这里可以根据statement block的scope实现叻,Mysql里通过begin end来划分一个statement block,在block里定义的变量范围也在这个block里,所以关于嵌套的游标循环我们可以多加一个begin end来区分他们所对应的error handler(注意在Mysql里同一个error的handler只能定义一次,多定义的话,在compile的过程中会提示里duplicate handler defination,所以NOT FOUND的handler就只能定义一次),在一个begin end里定义这个里面游标的NOT FOUND handler,

declare fetchSeqOk boolean; ## define the flag for loop judgement declare _seqname varchar(50); ## define the varient for store the data declare _value bigint(20); declare fetchSeqCursor cursor for select seqname, value from sys_sequence;## define the cursor declare continue handler for NOT FOUND set fetchSeqOk = true; ## define the continue handler for not found flag set fetchSeqOk = false; open fetchSeqCursor; fetchSeqLoop:Loop if fetchSeqOk then leave fetchSeqLoop; else fetch cursor into _seqname, _value; begin declare fetchSeqOk boolean default 'inner'; declare cursor2 cursor for select .... from ...;## define the cursor declare continue handler for NOT FOUND set fetchSeqOk = true; ## define the continue handler for n ot set fetchSeqOk = false; open cursor2; fetchloop2 loop if fetchSeqOk then else end if; end loop; close cursor2; end; end if; end Loop; close fetchSeqCursor; 

我把自己写的触发器写到这里,供大家参考,也作为我的一个备忘吧。

begin #声明一个变量用于while循环DECLARE i int;declare fetchSeqOk boolean; declare pid int;   #声明一个游标declare  cur_count cursor for select  object_id from mot_term_relationships where term_taxonomy_id = (select term_taxonomy_id   from mot_term_taxonomy  where term_id=old.term_id);declare continue handler for NOT FOUND set fetchSeqOk = true; #define the continue handler for not found flag ;set fetchSeqOk = false; /*得到删除term的父类  @parentId 父类的term_id*/select parent into @parentId   from mot_term_taxonomy  where term_id=old.term_id;#你删除的term对应的term_taxonomy_id     @term_taxonomy_id_oldselect term_taxonomy_id into @term_taxonomy_id_old  from mot_term_taxonomy  where term_id=old.term_id;if @parentId != '0'  then /*得到父类对应的term_taxonomy_Id,赋值给被删除term的文章,吧term对应的文章移动到它对应的父类下    @term_taxonomy_id_new 父类的term_taxonomy_id*/select  term_taxonomy_id  into @term_taxonomy_id_new  from mot_term_taxonomy  where term_id=@parentId;/*如果这个term有子分类 子分类的级别分别向上提一级,就是他的第一级子分类的parent id改为删除term的parent id*/update mot_term_taxonomy set parent=@parentId where parent=old.term_id;/*把term对应的文章移动到它对应的父类下*/ /*循环查出这个分类对应的文章*/#打开游标open cur_count;#游标循环cur_count:LOOPFETCH cur_count INTO pid; #游标出口if fetchSeqOk THEN  leave cur_count;   #利用游标做的操作else /*判断父类是否已经有这篇文章了如果有了就不给做任何操作,如果没有则可以需改(不然会出现主键重复的问题)*/  select count(*) into @count from mot_term_relationships  where term_taxonomy_id =@term_taxonomy_id_new and object_id=pid;  IF  @count<>1 THENupdate mot_term_relationships set term_taxonomy_id = @term_taxonomy_id_new where term_taxonomy_id = @term_taxonomy_id_old and object_id=pid;  end if;end if;end LOOP;CLOSE cur_count;else  /*如果对应的parent id为0 则移动到默认分类下。*/ /*从option表中查出默认分类的term_id*/ select option_value into @term_id_def from mot_options where option_name='default_category'; /*根据查出来的term_id 查出对应的term_taxonomy_id */ select  term_taxonomy_id into @term_taxonomy_id_new  from mot_term_taxonomy  where term_id=@term_id_def ; /*如果这个term有子分类 子分类的级别分别向上提一级,就是他的第一级子分类的parent id改为删除term的parent id*/ update mot_term_taxonomy set parent=@parentId where parent=old.term_id; /*把对应的post移动到默认分类下。*/ update mot_term_relationships set term_taxonomy_id = @term_taxonomy_id_new where term_taxonomy_id=@term_taxonomy_id_old;end if;         /*对应删除mot_term_taxonomy 的记录*/        delete from mot_term_taxonomy   where  term_id=old.term_id;end



0 0