mysql 游标长度_MySQL 游标

MySQL 游标

SQL语句是“面向集合编程”,重点在于“获得什么”,而不是“如何获得”。

有时候我们不需要对查询结构集的每一条都进行相同的操作,而是只操作其中的某些行,这时候就需要面向过程的编程方法,而游标就是面向过程编程方式的体现

游标就相当于“指针”,它一次只指向一行

游标的作用就是用于对查询数据库所返回的记录进行遍历,以便进行相应的操作

游标的使用

声明(给定结果集)、打开、通过游标获取数据、关闭、释放游标

声明,给定结果集,存储过程结束后游标就被清理

DECLARE cursor_name CURSOR FOR (SELECT...);

打开游标,将结果集送到游标工作区

OPEN cursor_name;

通过游标获取数据

游标先判断当前行是否为空,若为空则改变done,若不为空则将数据存放到临时变量中,读取后进入下一行为下次读取做准备。

一定要想明白FETCH的运行方式,不然可能会出现重复FETCH到数据的情况

FETCH cursor_name INTO (变量名s);

关闭游标

CLOSE cursor_name;

因为每次调用FETCH游标就会尝试下一行,因此还要声明一个 NOT FOUND处理程序来处理游标读取不到下一行的情况

DECLARE CONTINUE HANDLER FOR not found SET done = true;

或者

DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done = true;

SQLSTATE '02000'可以看做和not found一样,SQLSTATE '02000'是当没有更多的行以供循环时出现的一个条件。

上面两种都可行,至于done赋值为true还是为1,就要看done是如何定义的,当然定义为INIT的为可以初始化为true

使用举例1

现有如下数据表

mysql> select * from t;

+----+------+-----------------+

| id | nums | content |

+----+------+-----------------+

| 1 | 2 | NULL |

| 2 | 6 | 二六一十二 |

| 3 | 3 | 三三得九 |

+----+------+-----------------+

3 rows in set (0.00 sec)

我们通过游标读取每一行并实现将nums导入到新数据表中,在实际工作中这种方式可以大大减少我们"分表"时的操作难度。

DELIMITER //

CREATE PROCEDURE transferData()

BEGIN

DECLARE temp_num INT;

DECLARE done BOOLEAN DEFAULT false;

DECLARE cur CURSOR FOR select nums FROM t;

DECLARE continue HANDLER FOR not found SET done = true;

CREATE TABLE IF NOT EXISTS t2 (auto_id int PRIMARY KEY AUTO_INCREMENT, val int not null);

OPEN cur;

REPEAT

IF NOT done THEN

FETCH cur INTO temp_num;

INSERT INTO t2 (val) VALUES (temp_num);

END IF;

UNTIL done=true END REPEAT;

CLOSE cur;

SELECT * from t2;

END//

DELIMITER ;

执行该存储过程后自动显示如下结果:

mysql> select * from t2;

-> //

+---------+-----+

| auto_id | val |

+---------+-----+

| 1 | 2 |

| 2 | 6 |

| 3 | 3 |

| 4 | 3 |

+---------+-----+

4 rows in set (0.00 sec)

我们会发现,为什么这里多了一行数据?看起来是被重复FETCH并插入了,究其原因,是因为没有理清楚FETCH的运作方式---没有搞清楚什么时候FETCH会改变done

如果我们改成

CREATE PROCEDURE transferData2()

BEGIN

DECLARE temp_num INT;

DECLARE done BOOLEAN DEFAULT false;

DECLARE cur CURSOR FOR select nums FROM t;

DECLARE continue HANDLER FOR not found SET done = true;

CREATE TABLE IF NOT EXISTS t3 (auto_id int PRIMARY KEY AUTO_INCREMENT, val int not null);

OPEN cur;

REPEAT

FETCH cur INTO temp_num;

IF NOT done THEN

INSERT INTO t3 (val) VALUES (temp_num);

END IF;

UNTIL done=true END REPEAT;

CLOSE cur;

SELECT * from t3;

END//

则结果会符合我们的预期

mysql> select * from t3//

+---------+-----+

| auto_id | val |

+---------+-----+

| 1 | 2 |

| 2 | 6 |

| 3 | 3 |

+---------+-----+

3 rows in set (0.00 sec)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值