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

原创 2015年07月08日 20:55:02


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_old
select 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:LOOP
	FETCH 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 THEN

		update 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



版权声明:转载请注明出处哦!!

相关文章推荐

MySQL 存储过程游标嵌套,触发器调用存储过程

#存储过程 drop procedure if exists update_pointer; CREATE PROCEDURE update_pointer(IN ckindId int) BEGIN...

Mysql存储过程游标触发器

  • 2015年07月09日 21:15
  • 2KB
  • 下载

MySQL必知必会笔记(四)存储过程 游标 触发器

第二十三章 使用存储过程     MySQL5 中添加了存储过程的支持。     大多数SQL语句都是针对一个或多个表的单条语句。并非所有的操作都怎么简单。经常会有一个完整的操作需要多条才能完成  ...

6.《MySQL必知必会》视图,存储过程,游标与触发器

注:博客中总结《MySQL必知必会》中的知识点,第22,23,24,25章的核心内容;涉及到的操作符:VIEW,PROCEDURE,CALL,DECLARE,IF,REPEAT,END,FETCH,T...

mysql数据库数据改变监控 触发器 游标 new. old. java监控比对 最终是在后端java进行比对

最近有了这样一个需求,就是数据改变项,需要进行突出显示,而这就涉及到一个数据比对的问题,在网上搜了一下解决方案,没有明确的方案,大致上也只有两种: 一种通过数据库来进行处理,暂时以mysql为例子 一...

MySQL必知必会笔记(六)存储过程 游标 触发器

第二十三章 使用存储过程     MySQL5 中添加了存储过程的支持。     大多数SQL语句都是针对一个或多个表的单条语句。并非所有的操作都怎么简单。经常会有一个完整的操作需要多条才...
  • YMS_KK
  • YMS_KK
  • 2015年09月24日 15:48
  • 1026
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于mysql写触发器中运用游标的问题。
举报原因:
原因补充:

(最多只允许输入30个字)