mysql中游标的使用案例详解(学习笔记)这篇讲得相当直白好懂了。

索引:

  1. cursor 基础讲解
  2. mysql 循环
  3. 书上的整合代码

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 '' 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 '' 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;

这些活到底谁来做好呢 ? 是上层应用程序 还是 数据库 ? 。 。。 待更新。。

MySQL Crash Course #16# Chapter 24. Using Cursors + mysql 循环的更多相关文章

  1. MySQL Crash Course #15# Chapter 23. Working with Stored Procedures

    以前写过类似的东西,用来自动生成数据. 你可以将 Stored Procedure 理解为可以重复使用的批处理文件. Stored Procedure 非常有用,我们应该尽可能地去使用它. 那么,应用 ...

  2. MySQL Crash Course #06# Chapter 13. 14 GROUP BY. 子查询

    索引 理解 GROUP BY 过滤数据 vs. 过滤分组 GROUP BY 与 ORDER BY 之不成文的规定 子查询 vs. 联表查询 相关子查询和不相关子查询. 增量构造复杂查询 Always ...

  3. MySQL Crash Course #05# Chapter 9. 10. 11. 12 正则.函数. API

    索引 正则表达式:MySQL only supports a small subset of what is supported in most regular expression implemen ...

  4. MySQL Crash Course #02# Chapter 3. 4 通配符. 分页

    索引 查看表.文档操作 检索必须知道的两件事 数据演示由谁负责 通配符.非必要不用 检索不同的行 限制结果集.分页查找 运用数据库.表全名 命令后加分号对于很多 DBMS 都不是必要的,但是加了也没有 ...

  5. MySQL Crash Course #08# Chapter 16. Using Different Join Types

    记文档还是相当重要的! 索引 假名的三个用途 自交(Self Joins) 自然交(Natural Joins) Outer Joins Using Table Aliases Using alias ...

  6. MySQL Crash Course #13# Chapter 21. Creating and Manipulating Tables

    之前 manipulate 表里的数据,现在则是 manipulate 表本身. INDEX 创建多列构成的主键 自动增长的规定 查看上一次插入的自增 id 尽量用默认值替代 NULL 外键不可以跨引 ...

  7. MySQL Crash Course #11# Chapter 20. Updating and Deleting Data

    INDEX Updating Data The IGNORE Keyword Deleting Data Faster Deletes Guidelines for Updating and Dele ...

  8. MySQL Crash Course #10# Chapter 19. Inserting Data

    INDEX BAD EXAMPLE Improving Overall Performance Inserting Multiple Rows INSTEAD OF Inserting a Singl ...

  9. MySQL Crash Course #04# Chapter 7. 8 AND. OR. IN. NOT. LIKE

    索引 AND. OR 运算顺序 IN Operator VS. OR NOT 在 MySQL 中的表现 LIKE 之注意事项 运用通配符的技巧 Understanding Order of Evalu ...

随机推荐

  1. C++和Java中枚举enum的用法

    在C++和java中都有枚举enum这个关键字,但是它们之间又不太一样.对于C++来说,枚举是一系列命名了的整型常量,而且从枚举值转化为对应的整型值是在内部进行的.而对于Java来说,枚举更像一个类的 ...

  2. HUSTM 1601 - Shepherd

    题目描述 Hehe keeps a flock of sheep, numbered from 1 to n and each with a weight wi. To keep the sheep ...

  3. POJ-2336 Ferry Loading II(简单DP)

    Ferry Loading II Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3763 Accepted: 1919 Desc ...

  4. c++中system("pause")的作用和含义

    简单来说就是暂停的意思,一般在LINUX编程时会用到,等待接收信号,才会重新运行 . 在进行C/C++编程的时候,在运行程序查看输出效果时,会出现窗口闪一下就关闭的情况. 在C语言中一般通过添加get ...

  5. opencv学习之PyImageSearch

    Practical Python and OpenCV+ Case Studies 是一本opencv的入门书籍 强烈推荐一个老外的网站,pyimagesearch 网址:https://www.py ...

  6. POJ 2653 - Pick-up sticks - [枚举+判断线段相交]

    题目链接:http://poj.org/problem?id=2653 Time Limit: 3000MS Memory Limit: 65536K Description Stan has n s ...

  7. 【紫书】【重要】Abbott's Revenge UVA - 816 bfs 复杂模拟 带方向参数的迷宫

    题意:一个迷宫,每个交叉路口有一路标,限制了你从某方向进入该路口所能进入的路口. 题解:1.对于方向的处理:将node多增加一维dir,通过一个const 字符数组 加 上dir_id函数 以及一个方 ...

  8. In MySQL, a zero number equals any string

    最近在做项目的过程中发现了一个问题 数据库表 test  有个字段是 target_id  int(11),这个字段可能为零 使用如下查询 select * from test where targe ...

  9. sparkuser is not in the sudoers file. This incident will be reported.

    切换到root身份$su -(注意有- ,这和su是不同的,在用命令"su"的时候只是切换到root,但没有把root的环境变量传过去,还是当前用户的环境变量,用"su ...

  10. mysql清空有外键关联的表

    第一种:(不要外键约束) 手动删除外键约束: 删除表数据 第二种:(保留外键约束) SET FOREIGN_KEY_CHECKS = 0;   TRUNCATE TABLE 表名;  SET FORE ...