MySQL检索操作返回一组成为结果集的行。使用简单的SELECT语句,例如,没有办法得到第一行、下一行或前10行,也不存在每次一行的处理所有行的简单办法。有时,需要再检索出来的行中前进或后退一行或多行。这就是使用游标的原因。
MySQL游标只能用于存储过程(和函数)。
创建游标
DELIMITER //
CREATE PROCEDURE processorders()
BEGIN
DECLARE ordernumbders CURSOR
FOR
SELECT ordernum FROM orders;
END//
DELIMITER ;
这个存储过程并没有做很多事情,DECLARE语句用来定义和命名游标,这里为(二声)ordernumbers。存储过程处理完成后,游标就消失,因为它只能用于存储过程(或函数)。
打开和关闭游标
打开之前定义的游标:
OPEN ordernumbers;
在处理open语句时,执行查询,存储检索除的数据以供浏览和滚动。
游标处理完成后,应当使用如下语句关闭游标:
CLOSE ordernumbers;
CLOSE释放游标使用的所有内部内存和资源,因此在每个游标不再需要时都应该关闭。但是,当再次需要使用该游标的时候,无需重新定义,只需要使用OPEN语句就可以重新打开游标。
隐含关闭:如果你不明确关闭游标,MySQL将会在到达END语句时自动关闭它。
使用游标数据
在一个游标被打开后,可以使用FETCHE语句分别访问它的每一行。FETCH指定检索什么数据(所需的列),检索出来的数据存储在什么地方。它还可以向前移动游标中的内部指针,使吓一跳FETCH语句检索下一行(不重复读取同一行)。
mysql> CREATE PROCEDURE processorders()
-> BEGIN
-> DECLARE o INT;
-> DECLARE t DECIMAL(8,2);
-> DECLARE down BOOLEAN DEFAULT 0;
-> DECLARE ordernumbers CURSOR
-> FOR
-> SELECT order_num FROM orders;
-> DECLARE CONTINUE HANDLER FOR SQLSTATE "02000" SET down=1;
-> CREATE TABLE IF NOT EXISTS ordertotals(order_num INT,total DECIMAL(8,2));
-> OPEN ordernumbers;
-> REPEAT
-> FETCH ordernumbers INTO o;
-> CALL ordertotal(o,1,t);
-> INSERT INTO ordertotals(order_num,total) VALUES (o,t);
-> UNTIL down END REPEAT;
-> CLOSE ordernumbers;
-> END//
mysql> SELECT * FROM ordertotals//
+-----------+---------+
| order_num | total |
+-----------+---------+
| 20005 | 158.86 |
| 20009 | 40.78 |
| 20006 | 58.30 |
| 20007 | 1060.00 |
| 20008 | 132.50 |
+-----------+---------+
这里面需要用到之前存储过程那个章节中讲到的ordertotal()函数。