一、游标简介
SELECT语句得到的是一个结果集,有时我们需要对结果集中的单条数据进行处理。
这时就需要使用游标,游标定义时和一个SELECT语句的结果集关联在一起。
游标执行这个结果集,可以在结果集中一行一行的移动,并可以代表执行的单行数据。
游标就类似指针,可以指向一行数据,并且在数据集上移动。
注:只能在存储过程中才能使用游标。
二、创建游标
创建游标格式:
DECLARE 游标名 CURSOR FOR select语句
这样就在指定的select语句的结果集上建立了游标。
DELIMITER // CREATE PROCEDURE testCursor() BEGIN DECLARE cc CURSOR FOR SELECT order_num FROM orders; END // DELIMITER ;
游标的生命周期,只限于存储过程中有效。存储过程结束后,游标也就消失了。
三、开启、关闭游标
游标定义后还需要打开方可使用,当游标不需要使用时,将游标关闭。
DELIMITER // CREATE PROCEDURE testCursor() BEGIN DECLARE cc CURSOR -- 创建游标 FOR SELECT order_num FROM orders; OPEN cc; -- 打开游标 CLOSE cc; -- 关闭游标 END // DELIMITER ;
四、使用游标
游标打开后,可以使用FEACH访问每一行,FEACH初始情况下指向第一行。
每一次执行FEACH都会后移一行,
DELIMITER // CREATE PROCEDURE testCursor() BEGIN DECLARE orderNum INT; -- 存放检索的order_num DECLARE cc CURSOR -- 创建游标 FOR SELECT order_num FROM orders; OPEN cc; -- 打开游标 FETCH cc INTO o; -- 如果结果集有多列,INTO value1,value2...即可 CLOSE cc; -- 关闭游标 END // DELIMITER ;
将第一行数据放入变量o中,注意变量o的数据类型要和返回的数据类型一致。
如果游标有多列,cursor INTO value1,value2.。value变量的类型要和对应返回值类型一致。
五、使用游标遍历结果集
税率计算存储过程
DELIMITER // CREATE PROCEDURE ordertotal( IN ordernumber DECIMAL(8,2),-- 订单编号 IN tax BOOLEAN , -- 该商品是否计算税金,1为true计算,0位false不计算 OUT total DECIMAL(8,2) -- 最后价格 ) BEGIN DECLARE total_tmp DECIMAL(8,2); -- 含税价格 DECLARE tax_t INT DEFAULT 6; -- 定义默认税率,6% SELECT SUM(quantity*item_price) FROM orderitems WHERE order_num = ordernumber INTO total_tmp; -- 首先计算商品不含税总价 IF tax THEN -- 如果tax为1(true) 计算含税总价 SELECT total_tmp * (1 + (tax_t / 100)) INTO total_tmp; -- END IF; SELECT total_tmp INTO total; -- 将最后价格赋给total END// DELIMITER ; -- 示例 -- CALL ordertotal(20005,1, @total); -- 计算20005号订单价格,含税, 1为true,0为false -- SELECT @total; -- 显示计算后总价
游标遍历订单,并调用税率计算存储过程计算总价值
DELIMITER // CREATE PROCEDURE processorders() BEGIN DECLARE o INT; -- DECLARE done BOOLEAN DEFAULT 0; DECLARE t DECIMAL(8,2); -- 创建游标 DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- 设置结束状态语句,可以看做一个监听器,当出现SQLSTATE为02000时执行SET done=1. 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 -- 使用FETCH访问游标的行,将数据(订单编号)放入变量o FETCH ordernumbers INTO o; -- 调用税率计算存储过程 CALL ordertotal(o,1,t); INSERT INTO ordertotals(order_num,total) VALUES(o,t); UNTIL done END REPEAT;-- done为1时终止循环 -- 关闭游标 CLOSE ordernumbers; END// DELIMITER ; CALL processorders(); -- 调用 SELECT * FROM ordertotals; -- 新表名
参考资料:
《MySQL必知必会》
原文:https://www.cnblogs.com/huang-changfan/p/10719241.html