mysql中游标的使用案例详解(学习笔记)这篇讲得相当直白好懂了。
索引:
- cursor 基础讲解
- mysql 循环
- 书上的整合代码
cursor 基础讲解
cursor 有点类似于 JDBC 中的 ResultSet ,允许我们在执行 SELECT 之后,一行一行地 FETCH 数据。
它只能被用在存储过程中!如果把存储过程比作函数,cursor 只能在这个函数体中(存储过程的内部)定义、打开、关闭,一旦存储过程执行完毕,它将不再存在(可以把 cursor 理解为一个局部变量)。
定义一个 cursor ,这个时候并没有执行 SELECT 语句:
CREATE PROCEDURE processorders() BEGIN DECLARE ordernumbers CURSOR FOR SELECT ordernum FROM orders; END;
打开 cursor,SELECT 语句就是在这个时候被执行的,数据被缓存到 cursor 中,在这之后可以 FETCH 数据:
OPEN ordernumbers;
关闭 cursor ,释放 cursor 所占用的所有内存和资源, 当然,即便不手动关闭,在存储过程结束时(执行到 END) cursor 也会自动关闭:
CLOSE ordernumbers;
接下来就是 FETCH 数据了,每次 FETCH 一次都是下一行!可以结合上面几个知识点做个小实验,上面是实验用的表:
DROP PROCEDURE IF EXISTS hello; DELIMITER // CREATE PROCEDURE hello() BEGIN -- 声明局部变量,用于临时存储 FETCH 结果 DECLARE o INT; -- 声明游标 DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- 打开游标(执行SELECT,缓存数据) OPEN ordernumbers; -- 取出第一个订单号放到 o 里,并打印 FETCH ordernumbers INTO o; SELECT o; -- 取出第二个订单号放到 o 里,并打印 FETCH ordernumbers INTO o; SELECT o; -- 关闭游标(释放内存、资源) CLOSE ordernumbers; -- 重新打开游标(重新执行SELECT,缓存数据) OPEN ordernumbers; -- 取出第 ? 个订单号放到 o 里,并打印 FETCH ordernumbers INTO o; SELECT o; -- 可以猜到,依然是第一个订单号 END // DELIMITER ; CALL hello();
mysql 循环
mySQL 本身的循环其实挺简单的,但是书上写的循环有点特殊。
基本循环示例:
while ↓
DROP PROCEDURE IF EXISTS hello; DELIMITER // CREATE PROCEDURE hello() BEGIN DECLARE v1 INT DEFAULT 5; WHILE v1 > 0 DO SET v1 = v1 - 1; SELECT v1; END WHILE; END // DELIMITER ; CALL hello();
repeat ↓
DROP PROCEDURE IF EXISTS hello; DELIMITER // CREATE PROCEDURE hello() BEGIN DECLARE v1 INT DEFAULT 5; REPEAT SET v1 = v1 - 1; SELECT v1; UNTIL v1 = 0 END REPEAT; END // DELIMITER ; CALL hello();
loop ↓
DROP PROCEDURE IF EXISTS hello; DELIMITER // CREATE PROCEDURE hello() BEGIN DECLARE v1 INT DEFAULT 5; label1: LOOP SET v1 = v1 - 1; SELECT v1; IF v1 > 0 THEN ITERATE label1; -- 继续循环 相当于continue END IF; LEAVE label1; -- 相当于 break END LOOP; END // DELIMITER ; CALL hello();
PS. 为了确保可以直接 COPY 到命令行执行,上面的代码缩进有点问题。。。
书上的循环示例:
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 DECLARE 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;
首先要看懂这句话
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000‘ SET done=1;
意思就是出现 SQLSTATE ‘02000‘ 这句话时就执行 SET done=1
而 SQLSTATE ‘02000‘ 等价于 not found ,它是在 FETCH 不到数据的时候出现的,因此拿不到数据的时候 done 变为真就结束循环了。。。
书上的整合代码
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(o, 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;
这些活到底谁来做好呢 ? 是上层应用程序 还是 数据库 ? 。 。。 待更新。。
原文地址:https://www.cnblogs.com/xkxf/p/8916426.html