0
点赞
收藏
分享

微信扫一扫

Mysql游标详解

yundejia 2022-01-28 阅读 72


Mysql游标详解

1.简单示例

  • 建表
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`address` varchar(20) DEFAULT NULL,
`score` varchar(10) DEFAULT NULL,
`rank` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
  • 导数
INSERT INTO `insidemysql`.`student` (`id`, `name`, `address`, `score`, `rank`) VALUES ('1', 'lawson', 'anhui_jinzhai', '98.2', '1%'),
('2', 'ting', 'anhui_suzhou', NULL, NULL),
('3', 'lee', 'anhui_hefei', NULL, NULL),
('4', 'tao', 'anhui_sanyuan', NULL, NULL);
  • 写cursor
drop procedure if exists getResultFromTest;
delimiter //

create procedure getResultFromTest(out result varchar(128))
begin
-- 存储过程所使用变量需申明
declare id int(11);
declare name varchar(20);
-- 遍历数据结束标志 注意位置顺序
DECLARE done INT DEFAULT FALSE;
-- 注意用别名 因为id在上面已经有定义所以需要使用表的别名区别
declare cur_test CURSOR for select t.id, t.name from student t;
-- 将结束标志绑定到游标
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

-- 打开游标
open cur_test;
repeat
fetch cur_test into id, name;
select id,name;
-- concat_ws函数用逗号后面的参数隔开 concat_ws(',','12','33','332') --> 12,33,332
select concat_ws(',',id,name) into result ;
until done
end repeat;
-- 注意关闭游标
close cur_test;
end;
//
delimiter ;
call getResultFromTest(@out);

执行结果如下:

mysql> call getResultFromTest(@out);
+------+--------+
| id | name |
+------+--------+
| 1 | lawson |
+------+--------+
1 row in set (0.00 sec)

+------+------+
| id | name |
+------+------+
| 2 | ting |
+------+------+
1 row in set (0.00 sec)

+------+------+
| id | name |
+------+------+
| 3 | lee |
+------+------+
1 row in set (0.00 sec)

+------+------+
| id | name |
+------+------+
| 4 | tao |
+------+------+
1 row in set (0.00 sec)

+------+------+
| id | name |
+------+------+
| 4 | tao |
+------+------+
1 row in set (0.00 sec)

稍有不解的是,这里为啥会多出一条记录出来?

同时,我将上述的sql修改成如下样子时【修改​​declare cur_test CURSOR for select t.id, t.name from student t;​​成​​declare cur_test CURSOR for select id, name from student ;​​】,就出现了执行失败的情况:

drop procedure if exists getResultFromTest;
-- delimiter表示以//结束编译
delimiter //

create procedure getResultFromTest(out result varchar(128))
begin
-- 存储过程所使用变量需申明
declare id int(11);
declare name varchar(20);
-- 遍历数据结束标志 注意位置顺序
DECLARE done INT DEFAULT FALSE;
-- 注意用别名 因为id在上面已经有定义所以需要使用表的别名区别
declare cur_test CURSOR for select id, name from student ;
-- 将结束标志绑定到游标
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

-- 打开游标
open cur_test;
repeat
fetch cur_test into id, name;
select id,name;
-- concat_ws函数用逗号后面的参数隔开 concat_ws(',','12','33','332') --> 12,33,332
select concat_ws(',',id,name) into result ;
until done
end repeat;
-- 注意关闭游标
close cur_test;
end;
//
delimiter ;
call getResultFromTest(@out);

为什么执行失败,我不理解了。

= == == == == = 更新于 20181026====================

偶得网友提醒,突然间明白,上述的这个存储过程执行失败的原因是:​​declare cur_test CURSOR for select id, name from student ;​​语句中的​​select id,name from student​​这一部分会将字段​​id,name​​当成存储过程中定义的变量,而不是表student中字段名。即**存储过程中定义的变量名在存储过程中是全局有效的,所以select中的字段不应该和declare的变量重名。**为验证此说法,可以将存储过程更改成如下:

begin    
declare id_1 int(11);
declare name_1 varchar(20);
DECLARE done INT DEFAULT FALSE;
declare cur_test CURSOR for select id, name from student;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;

open cur_test;
repeat
fetch cur_test into id_1, name_1;
select id_1,name_1;
until done
end repeat;
close cur_test;
end

然后调用,发现也是可以的。


举报

相关推荐

0 条评论