Mysql游标循环遍历

在大型的数据面前修改表内的内容,使用Mysql的游标实现 
牧牛遛马 
牧牛遛马根据在存储过程的接触上实际的使用过程在代码的每个逻辑后面加上注释来大致实现一下遍历数据表的逻辑

牧牛遛马 
踩过的雷区:

1、记不得游标的查询单词————–fetch

2、设置循环条件的代码写错———— 
declare continue handler for not found set flag = false; 
漏写for,handler错写成handle

3、游标查询的时候要赋值给多个变量,加逗号就可以了 (最后面一定要有分号)
fetch liuma into lmage,lmname; 
不能理解liuma里面有多条字段信息数据错误。

4、until 语句后面不能加分号 
正确———–until flag = false 
错误———–until flag = false;

5、变量在游标或者handler的后面定义报错: 
ERROR 1337 (42000): Variable or condition declaration after cursor or handler de 
claration

Surfing the code…

提个需求: 
更改表中的所有数据,规则如下 

如果年龄大于18,名字后面加上说自己是成年人; 
如果年龄小于18,名字后面加上说自己是未成年人; 

1、先来一张表 
这里便于演示,只显示了七条数据,根据实现的思想逻辑可以扩展到百万数据的更新。

mysql> select * from emp;
+----+--------+------+---------+
| id | name   | age  | dept_in |
+----+--------+------+---------+
|  1 | 张三   |   18 |       1 |
|  2 | 李四   |   18 |       1 |
|  3 | 王五   |   20 |       1 |
|  4 | 赵六   |   21 |       2 |
|  5 | 小强   |   12 |       3 |
|  6 | 大锤   |   12 |       3 |
|  7 | 中申通 |   23 |       3 |
+----+--------+------+---------+
7 rows in set (0.00 sec)

2、写一下游标遍历数据的代码

mysql> delimiter $$
mysql> create procedure muniu ()
    -> begin
    ->     declare lmage int(11);
    ->     declare lmname varchar(50);
    ->     declare flag int default true;#声明一个开关变量flag用于循环结束判断默
认是true;
    ->     declare liuma cursor for(select age,name from emp);#申明一个游标,名
字叫liuma,因为游标指向的表内有两个字段,需要两个变量存储,所有得申明两个变量;
    ->
    ->     declare continue handler for not found set flag = false;
    ->     open liuma;#打开游标
    ->
    ->     repeat
    ->         fetch liuma into lmage,lmname;#把游标的内容赋值到变量中。
    ->         if(lmage<18)
    ->             then update emp set name = concat(lmname,"说我是未成年人,读
书少") where age = lmage;
    ->         elseif(lmage>18 or lmage = 18)
    ->             then update emp set name = concat(lmname,"说我是成年人,不会
乱来")  where age = lmage;
    ->         end if;
    ->         until flag = false
    ->     end repeat;
    ->     close liuma;#关闭游标
    -> end$$
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql>
mysql>
mysql>
mysql> call muniu;
Query OK, 0 rows affected (0.51 sec)

mysql> select * from emp;
+----+------------------------------+------+---------+
| id | name                         | age  | dept_in |
+----+------------------------------+------+---------+
|  1 | 李四说我是成年人,不会乱来   |   18 |       1 |
|  2 | 李四说我是成年人,不会乱来   |   18 |       1 |
|  3 | 王五说我是成年人,不会乱来   |   20 |       1 |
|  4 | 赵六说我是成年人,不会乱来   |   21 |       2 |
|  5 | 大锤说我是未成年人,读书少   |   12 |       3 |
|  6 | 大锤说我是未成年人,读书少   |   12 |       3 |
|  7 | 中申通说我是成年人,不会乱来 |   23 |       3 |
+----+------------------------------+------+---------+
7 rows in set (0.00 sec)
  •  

从上面的代码运行中我们发现,当age重复的时候,他们的名字会出现错误,第一条应该是张三说,可是运行出来是李四说,第5条应该是小强说,运行出来是大锤说。 
这是因为我们在查询的时候使用的是age字段,每次更新数据的时候会把age相同的一起更新,第二次把第一次覆盖导致。 
要解决这个问题,需要在游标中传入一个主键参数,然后根据主键做条件,根据age做判断就可以解决。这里就先把数据更新为不重复数据,模拟age为主键的情况进行演示一下:

先更新一下数据

mysql>  update emp set name = "张三" where id =1;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update emp set age = 13 where id =1;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  update emp set name = "李四" where id= 2;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  update emp set name = "王五" where id= 3;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  update emp set name = "赵六" where id= 4;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  update emp set name = "小强" where id= 5;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  update emp set name = "大锤" where id= 6;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update emp set age=11 where id= 6;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  update emp set name = "中申通" where id= 7;
Query OK, 1 row affected (0.11 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from emp;
+----+--------+------+---------+
| id | name   | age  | dept_in |
+----+--------+------+---------+
|  1 | 张三   |   13 |       1 |
|  2 | 李四   |   18 |       1 |
|  3 | 王五   |   20 |       1 |
|  4 | 赵六   |   21 |       2 |
|  5 | 小强   |   12 |       3 |
|  6 | 大锤   |   11 |       3 |
|  7 | 中申通 |   23 |       3 |
+----+--------+------+---------+
7 rows in set (0.00 sec)
  • 一下游标过程存储:
mysql> delimiter $$
mysql> create procedure muniu ()
    -> begin
    ->     declare lmage int(11);
    ->     declare lmname varchar(50);
    ->     declare flag int default true;
    ->     declare liuma cursor for select age,name from emp;
    ->
    ->     declare continue handler for not found set flag = false;
    ->     open liuma;
    ->     repeat
    ->           fetch liuma into lmage,lmname;
    ->     if(lmage<18)
    ->                then update emp set name = concat(lmname,"说我是未成年人,
读书少")
    ->
    -> where age = lmage;
    ->             else
    ->                update emp set name = concat(lmname,"说我是成年人,不会乱
来") where
    ->
    -> age = lmage;
    ->             end if;
    ->
    ->         until flag = false
    ->     end repeat;
    ->    close liuma;
    -> end$$
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql>
mysql> call muniu;
Query OK, 0 rows affected (0.43 sec)

mysql> select * from emp;
+----+------------------------------+------+---------+
| id | name                         | age  | dept_in |
+----+------------------------------+------+---------+
|  1 | 张三说我是未成年人,读书少   |   13 |       1 |
|  2 | 李四说我是成年人,不会乱来   |   18 |       1 |
|  3 | 王五说我是成年人,不会乱来   |   20 |       1 |
|  4 | 赵六说我是成年人,不会乱来   |   21 |       2 |
|  5 | 小强说我是未成年人,读书少   |   12 |       3 |
|  6 | 大锤说我是未成年人,读书少   |   11 |       3 |
|  7 | 中申通说我是成年人,不会乱来 |   23 |       3 |
+----+------------------------------+------+---------+
7 rows in set (0.00 sec)

牧牛 
遛马

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值