MySQL游标G

database

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)

以上是 MySQL游标G 的全部内容, 来源链接: utcz.com/z/534403.html

回到顶部