使用游标
Posted 霖行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用游标相关的知识,希望对你有一定的参考价值。
使用游标
本章将讲授什么是游标以及如何使用游标。
游标
mysql检索操作返回一组称为结果集的行。这组行都是与SQL语句相匹配的行。使用简单的SELECT语句,没有办法得到第一行、下一行或前十行,也不存在每次仅修改结果集中某行的办法。
有时,需要在检索出来的行中前进或后退一行或多行。我们可以使用游标(cursor),它是一个存储在MySQL服务器上的数据库查询,并非一条SELECT语句,而是一个SELECT语句检索出的结果集。在存储了游标后,应用程序可以根据需要滚动或浏览其中的数据。
只能用于存储过程 MySQL游标只能用于存储过程(和函数)。
使用游标
使用游标需要几个步骤:
- 使用游标前,必须声明(定义)它。 此时并未检索数据,只是定义使用的SELECT语句。
- 声明后,必须打开游标以供使用。 此时使用定义的SELECT语句进行实际检索。
- 对于填有数据的游标,根据需要取出(检索)各行。
- 结束游标使用时,必须关闭游标。
声明游标后,可根据需要频繁地打开和关闭游标。游标打开后,可根据需要频繁地执行取操作。
创建游标
游标用DECLARE语句创建(MySQL必知必会——第二十三章使用存储过程)。DECLARE命名游标,并定义相应的SELECT语句。
定义名为ordernumbers的游标:
mysql> DELIMITER //
mysql> CREATE PROCEDURE processorders()
-> BEGIN
-> DECLARE ordernumbers CURSOR
-> FOR
-> SELECT order_num FROM orders;
-> END //
Query OK, 0 rows affected (0.04 sec)
mysql> DELIMITER ;
DECLARE语句用来定义和命名游标。存储过程处理完成后,游标就消失。
DELIMITER DELIMITER修改了命令行的默认语句结束符,若非命令行客户端,需将DELIMITER行删除,并且END后//改;,详情见MySQL必知必会——第二十三章使用存储过程。
打开和关闭游标
游标用OPEN CURSOR语句来打开:
OPEN ordernumbers;
处理OPEN语句时执行查询,存储检索出的数据以供浏览和滚动。
游标处理完成后可使用CLOSE语句关闭游标:
CLOSE ordernumbers;
CLOSE释放游标使用的所有内部内存和资源,因此每个游标不再需要时都应该关闭。
游标关闭后,需要重新打开才可使用。但声明过的游标,无需再次声明。
- 隐式关闭 如果不明确关闭游标,MySQL将在END语句时自动关闭游标。
使用游标数据
游标打开后,可以使用FETCH语句分别访问它的每一行。FETCH指定检索什么数据,检索出来的数据存储在什么地方。它还向前移动游标中的内部行指针,使下一条FETCH语句检索下一行。
从游标中检索 单个行 :
CREATE PROCEDURE processorders()
BEGIN
-- Declare local variables
DECLARE o INT;
-- Declare the cursor
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
-- Open the cursor
OPEN ordernumbers;
-- Get order number
FETCH ordernumbers INTO o;
-- Close the cursor
CLOSE ordernumbers;
END;
此语句中,FETCH用来检索当前行的order_num列(自动从第一行开始)到名为o的局部声明的变量中。
从游标中 循环检索 所有行:
CREATE PROCEDURE processorders()
BEGIN
-- Declare local variables
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
-- Declare the cursor
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
-- Declare continue handler
DELCARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- Open the cursor
OPEN ordernumbers;
-- Loop through all rows
REPEAT
-- Get order number
FETCH ordernumbers INTO o;
-- End of loop
UNTIL done END REPEAT;
-- Close the cursor
CLOSE ordernumbers;
END;
此语句与前一个不同的是,FETCH是在REPEAT内,因此它反复执行直到done为真(由UNTIL done END REPEAT;规定)。done用DEFAULT 0语句默认为假,并且在结束时使用以下语句设置为真:
DELCARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
此语句定义了一个CONTINUE HANDLER,它是在条件出现时被执行的代码。SQLSTATE '02000’是一个未找到条件,但REPEAT由于没有更多行供循环而继续时,出现这个条件。
- DECLARE语句的次序 DECLARE语句存在特定的次序。局部变量必须在定义任意游标或句柄前,而句柄必须在游标后定义。
调用此存储过程将定义几个变量和一个CONTINUE HANDLER,定义并打开一个游标,重复读取所有行,然后关闭游标。
- 重复或循环? 除了REPEAT语句外,MySQL还支持循环语句,可用来重复执行代码,直到使用LEAVE语句手动退出。
综合样例:
CREATE PROCEDURE processorders()
BEGIN
-- Declare local variables
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8,2);
-- Declare the cursor
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
-- Declare continue handler
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- Create a table to store the results
CREATE TABLE IF NOT EXISTS ordertotals
(order_num INT, total DECIMAL(8,2));
-- Open the cursor
OPEN ordernumbers;
-- Loop through all rows
REPEAT
-- Get order number
FETCH ordernumbers INTO o;
-- Get the total for this order
CALL ordertotal(0, 1, t);
-- Insert order and total into ordertotals
INSERT INTO ordertotals(order_num, total)
VALUES(o, t);
-- End of loop
UNTIL done END REPEAT;
-- Close the cursor
CLOSE ordernumbers;
END;
此样例,我们使用变量t来存储每个订单的合计。此存储过程还在运行中创建了一个新表,名为ordertotals,用来存储结果。FETCH取每个order_num,然后用CALL执行另一个存储过程(上章的样例)来计算每个订单带税的合计。最后用INSERT保存每个订单的订单号和合计。
可通过查询存储结果的新表,来查看数据。
以上是关于使用游标的主要内容,如果未能解决你的问题,请参考以下文章