一、游标简介
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必知必会》