概念:比如说1条sql语句取出N条结果集的资源,取出每条资源的接口/句柄,就是游标 也就是说如果取出多条结果,但是不都从数据库中取出来,而是告诉每条的结果的地址,然后取一条之后指针就会移到下一个数据地址,这种游动的标记就叫游标 游标使用的步骤: 1 declare声明 格式:declare 游标名 cursor for select_statement; 2 open 打开; 格式:open 游标名 3 fetch 取值; 格式:fetch 游标名 into var1,var2[...]; 4 close 关闭 格式:close 游标名; 例子: crate procedure p12() begin declare row_gid int;----声明变量要在声明游标之前 declare row_num int; declare row_name varchar(20); declare getgoods cursor for select gid,num,name from goods; open getgoods; fetch getgoods into row_id,row_num,row_name;---每执行一次fetch语句,游标指向下一个记录,但是当fetch语句个数超过总记录条数的话会报错,所以需要循环来辅助游标的执行,这样就不会过界了 select row_num,row_name; close getgoods; end$ 如何循环与游标相配合取出所有行 1-找出总共的行数来限制游标过界 crate procedure p12() begin declare row_gid int; declare row_num int; declare row_name varchar(20); declare cnt int default 0;---记录总条数 declare i int default 0;--循环次数 declare getgoods cursor for select gid,num,name from goods; select count(*) into cnt from goods; open getgoods; repeat----游标的意义在于我们可以在里面写更复杂的逻辑对取出来的每一行结果进行处理,而select* 则一下子都取出来的,实现不了复杂的逻辑 set i :=i+1; fetch getgoods into row_id,row_num,row_name; select row_num,row_name; until i>=cnt end repeat; close getgoods; end$ 游标取值越界时,有标记,利用标记来结束 在mysql cursor中,可以declare continue handle来操作1个越界标识 格式:declare continue handler for NOT FOUND statement; 2-设置一个越界标记来限制游标过界 crate procedure p15() begin declare row_gid int; declare row_num int; declare row_name varchar(20); declare you int default 1; declare getgoods cursor for select gid,num,name from goods; declare continue handler for NOT FOUND set you:=0; open getgoods; repeat fetch getgoods into row_id,row_num,row_name; select row_num,row_name; until you=0 end repeat; close getgoods; end$ 这个例子执行结果,例如数据库有三种商品,按id排序,猫狗猪,就三条数据,执行完代码之后的结果是1猫2狗3猪4猪,可以看到最后一次是多余查出来的,原因就是第四次执行repeat时,fetch--->没取到数据----》触发NOT FOUND--->set you:=0---->continue---->继续执行后面的sql语句----->select row_num,row_name---->最后一行,被取出2次,但是如果NOT FOUND后,后面的select不再执行,最后也就不会多取一行了----》声明处理的handler不再是continue,而是exit,即可达到目的 declare exit handler for NOT FOUND statement; exit 与continue 的区别是,exit出发后,后面的语句不再执行 crate procedure p16() begin declare row_gid int; declare row_num int; declare row_name varchar(20); declare you int default 1; declare getgoods cursor for select gid,num,name from goods; declare exit handler for NOT FOUND set you:=0; open getgoods; repeat fetch getgoods into row_id,row_num,row_name; select row_num,row_name; until you=0 end repeat; close getgoods; end$ 除了continue,exit外,还有一种undo handler,continue是触发后,后面的语句继续执行,exit是触发后,后面的语句不再执行,undo是触发后,前面的语句撤销(但是,目前mysql还不支持undo) 但是现在我就要用continue来解决多读取一行的问题,其实p15,p16在执行的时候逻辑上有点不严谨,如果刚开始就一条数据都没有,首次执行就出发了you=0,所以要在输出数据之前就确定本次的变量是有值的 crate procedure p17() begin declare row_gid int; declare row_num int; declare row_name varchar(20); declare you int default 1; declare getgoods cursor for select gid,num,name from goods; declare continue handler for NOT FOUND set you:=0; open getgoods; fetch getgoods into row_id,row_num,row_name;---->在下面的输出之前要先fetch一下,如果没有值则会触发you=0,repeat会执行一次,输出空数据了,如果有 就会输出数据,执行repeat输出上一个变量的值,所以就算是continue的话,repeat里面的fetch语句后没有什么东西了,也就不会执行什么了,然后跳到下一次循环了 repeat select row_num,row_name; fetch getgoods into row_id,row_num,row_name; until you=0 end repeat; close getgoods; end$ 上面例子p17的逻辑才更准确,repeat与do...while类似,是先执行,然后在第二次执行之前 进行条件判断,while是满足条件之后才会执行代码,所以上例子p17当总共有0条数据会输出一个空值,大于0条时,顺序输出结果而且不会发生重复输出的情况,而while 则是一条空的结果都不输出
mysql中游标越界exit_mysql--游标
最新推荐文章于 2021-03-05 01:04:50 发布