游标cursor
游标cursor
MySQL检索操作返回一组称为结果集的行。这组返回的行都是与SQL语句相匹配的零或多
行。简单的SELECT语句没办法得到第一行、下一行或前10行,也不存在每次一行的处理
所有行的简单方法,即批量处理行。
故要检索出来的行中前进或后退一或多行时,可以用游标。
游标是一个存储在MySQL服务器上的数据库查询,不是一条SELECT语句,而是被该语句
检索出来的结果集。在存储了游标后,应用程序可以根据需要滚动或浏览其中的数据。
主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改
只能用于存储过程,MySQL游标只能用于存储过程和函数
使用游标
- 使用前,先声明游标,这一过程实际上没有检索数据,只是定义要使用的SELECT语句
- 一旦声明后,必须打开游标以供使用,这个过程用前面定义的SELECT语句把数据实际检
- 索出来
- 对于填有数据的游标,根据需要检索各行
- 结束游标使用时,要关闭游标
创建游标
DECLARE命名创建游标,并定义相应的SELECT语句,根据需要,带WHERE和其他语句
例一,定义ordernumbers游标,检索所有订单的SELECT语句
1 CREATE PROCEDURE processorders() 2 BEGIN 3 DECLARE ordernumbers CURSOR 4 FOR 5 SELECT order_num FROM orders; 6 END;
DECLARE语句用来定义命名游标ordernumbers
存储过程处理完后,游标消失,因为游标仅局限于存储过程
打开和关闭游标
1 OPEN ordernumbers;
在处理OPEN语句时执行查询,存储检索出的数据以供浏览和滚动。
1 CLOSE ordernumbers;
CLOSE释放游标使用道德所有内部内存和资源,因此在每个游标不再需要时都应该关闭。
游标关闭后,若没有重新打开,则不能再使用,但使用声明过的游标不需要再次声明,用
OPEN语句打开即可。
如果不明确关闭游标,MySQL将在到达END语句时自动关闭。
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare the cursor 4 DECLARE ordernumbers CURSOR 5 FOR 6 SELECT order_num FROM orders; 7 8 -- OPEN the cursor 9 OPEN ordernumbers; 10 11 -- CLOSE the cursor 12 CLOSE ordernumbers; 13 END;
使用游标
游标被打开后,使用FETCH语句分别访问它的每一行。FETCH指定检索什么数据,检索
出来的数据存储在什么地方。游标还向前移动游标中的内部行指针,使下一条FETCH语句
检索下一行(不重复读取同一行)
例二、从游标中检索单个行:
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare local varitables 4 DECLARE o INT; 5 6 -- Declare the cursor 7 DECLARE ordernumbers CURSOR 8 FOR 9 SELECT order_num FROM orders; 10 11 -- Open the cursor 12 OPEN ordernumbers; 13 14 -- Get order number 15 FETCH ordernumbers INTO o; 16 17 -- Close the cursor 18 CLOSE ordernumbers; 19 END;
其中FETCH用来检索当前行的order_num列,自动从第一行开始,到一个名为o的局部声明的变量中,检索出的数据不做处理。
例三、循环检索数据,从第一行到最后一行:
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare local varitables 4 DECLAE done BOOLEAN DEFAULT 0; 5 DECLARE o INT; 6 7 -- Declare the cursor 8 DECLARE ordernumbers CURSOR 9 FOR 10 SELECT order_num FROM orders; 11 12 -- Declare continue handler 13 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 14 15 -- Open the cursor 16 OPEN ordernumbers; 17 18 --loop through all rows 19 REPEAT 20 21 -- Get order number 22 FETCH ordernumbers INTO o; 23 24 -- End of loop 25 UNTIL done END REPEAT; 26 27 -- Close the cursor 28 CLOSE ordernumbers; 29 END;
使用FETCH检索当前order_num到声明的名为o的变量中,但与例一不同在于,FETCH是在REPEAT内,因此它反复执行知道done为真(DECLAE done BOOLEAN DEFAULT 0;)(UNTIL done END REPEAT;)
当(DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;)时done为真
这里定义了一个CONTINUE HANDLER,即条件出现时被执行的代码,当SQLSTATE '02000'出现时,done为1
SQLSTATE '02000'是一个未找到条件,当REPEAT循环完没法继续时,出现这个条件
如果调用这个存储过程,他将定义几个变量和一个CONTINUE HANDLER,定义并打开一个游标,重复读取所有行,然后关闭游标。
例四、对取出的数据进行
1 CREATE PROCEDURE processorders() 2 BEGIN 3 -- Declare local varitables 4 DECLARE done BOOLEAN DEFAULT 0; 5 DECLARE o INT; 6 DECLARE t DECIMAL(8,2); 7 8 -- Declare the cursor 9 DECLARE ordernumbers CURSOR 10 FOR 11 SELECT order_num FROM orders; 12 -- Declare continue handler 13 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 14 15 -- Create a table to store the results 16 CREATE TABLE IF NOT EXISTS ordertotals 17 (order_num INT, total DECIMAL(8,2)); 18 19 -- Open the cursor 20 OPEN ordernumbers; 21 22 --loop through all rows 23 REPEAT 24 25 -- Get order number 26 FETCH ordernumbers INTO o; 27 28 --Get the total for this order 29 CALL ordertotal(o,1,t); 30 31 -- Insert order and total into ordertotals 32 INSERT INTO ordertotals(order_num,total) 33 VALUES(o,t); 34 35 -- End of loop 36 UNTIL done END REPEAT; 37 38 -- Close the cursor 39 CLOSE ordernumbers; 40 END;
增加变量t存储每个订单的合计。此存储过程还在运行中创建了一个新表(CREATE TABLE IF NOT EXISTS ordertotals),这个表将保存存储过程生成的结果。
FETCH取每个order_num,然后用CALL执行另一个存储过程来计算每个订单的带税的合计,结果存储到t。
最后用INSERT保存每个订单的订单号和合计。
可以用SELECT语句查看此存储过程创建的表
1 SELECT* FROM ordertotals;