目录

  • 什么是游标?
  • 使用游标
  • 创建游标
  • 打开和关闭游标
  • 使用游标数据

什么是游标?

游标(cursor):是一个存储在MySQL服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。
使用原因:有时,需要在检索出来的行中前进或后退一行或多行等各种原因。
作用:在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改。

只能用于存储过程:不像多数DBMS,MySQL游标只能用于存储过程(和函数)。

使用游标

  • 在能够使用游标前,必须声明(定义)它;
  • 一旦声明后,必须打开游标以供使用;
  • 对于填有数据的游标,根据需要取出(检索)各行;
  • 在结束游标使用时,必须关闭游标。

创建游标

游标用DECLARE … CURSOR FOR [SELECTY语句] 语句创建。

CREATE PROCEDURE processorders() 
BEGIN 
	DECLARE ordernumbers CURSOR 
	FOR 
	SELECT order_num FROM orders;
END;

打开和关闭游标

OPEN ordernumbers;
CLOSE ordernumbers;

CLOSE释放游标使用的所有内部内存和资源,因此在每个游标不再需要时都应该关闭。

隐含关闭:如果不明确关闭游标,MySQL将会在到大END语句时自动关闭它。

使用游标数据

在一个游标被打开后,可以使用FETCH语句分别访问它的每一行。

CREATE PROCEDURE processorders() 
BEGIN 
	-- 声明变量 
	DECLARE done BOOLEAN DEFAULT 0; 
	DECLARE o INT; 
	
	-- 声明游标 
	DECLARE ORDERNUMBERS cursor 
	FOR 
	SELECT order_num FROM orders; 

	-- 声明程序运行条件 
	-- 该条件指出当SQLSTATE '02000'出现时,SET done=1
	-- SQLSTATE '02000'是一个未找到的条件,当REPEAT由于没有更多的行提供循环不能继续时,出现这个条件
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 

	-- 打开游标 
	OPEN ordernumbers; 

	-- 遍历所有行 
	REPEAT 
		-- 获得order number 
		FETCH ordernumbers INTO o; 

	-- 结束遍历 
	UNTIL done END REPEAT; 

	-- 关闭游标 
	CLOSE ordernumbers; 
END;

DECLARE语句次序:用DECLARE语句定义的局部变量必须在定义任意游标或任意句柄之前定义,而句柄(handle)必须在游标之后定义。不遵循此顺序将产生错误消息。
通常REPEAT语句的语法使它更适合于对游标进行循环。

使用游标对数据进行实际的处理(完善上述存储过程),该程序使用到上一节的存储过程ordertotal(…)。

CREATE PROCEDURE processorders() 
BEGIN 
	-- 声明变量 
	DECLARE done BOOLEAN DEFAULT 0; 
	DECLARE o INT; 
	DECLARE t DECIMAL(8, 2); 
	
	-- 声明游标 
	DECLARE ORDERNUMBERS cursor 
	FOR 
	SELECT order_num FROM orders; 

	-- 声明程序运行条件 
	-- 该条件指出当SQLSTATE '02000'出现时,SET done=1
	-- SQLSTATE '02000'是一个未找到的条件,当REPEAT由于没有更多的行提供循环不能继续时,出现这个条件
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; 

	-- 创建一个表来存储结果
	CREATE TABLE IF NOT EXISTS ordertotals 
		(order_num INT, total DECIMAL(8, 2));

	-- 打开游标 
	OPEN ordernumbers; 

	-- 遍历所有行 
	REPEAT 
		-- 获得order number 
		FETCH ordernumbers INTO o; 

		-- 获得当前order的total
		CALL order total(o, 1, t);

		-- 将当前order和total插入表ordertotals中
		INSERT INTO ordertotals(order_num, total) 
		VALUES(o, t);

	-- 结束遍历 
	UNTIL done END REPEAT; 

	-- 关闭游标 
	CLOSE ordernumbers; 
END;

此存储过程不返回结果,可以查询结果表。

SELECT * FROM ordertotals;