MySQL Crash Course #16# Chapter 24. Using Cursors + mysql 循环

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 ‘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

时间: 2024-10-29 05:14:35

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

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

之前 manipulate 表里的数据,现在则是 manipulate 表本身. INDEX 创建多列构成的主键 自动增长的规定 查看上一次插入的自增 id 尽量用默认值替代 NULL 外键不可以跨引擎 添加字段与删除字段 & 定义外键 复杂表结构的修改 删除表与修改表名 非常工整的 . .模范脚本: CREATE TABLE customers ( cust_id int NOT NULL AUTO_INCREMENT, cust_name char(50) NOT NULL , cust_a

MySQL Crash Course #14# Chapter 22. Using Views

索引 视图是啥 为什么需要视图 使用视图的规则 如何使用视图 视图应用实例 别用视图更新数据! 视图是啥 理解视图的最佳方式就是看下面这个例子. SELECT cust_name, cust_contact FROM customers, orders, orderitems WHERE customers.cust_id = orders.cust_id AND orderitems.order_num = orders.order_num AND prod_id = 'TNT2'; 上面的请

mysql 5.7.16多源复制

转 http://www.cnblogs.com/yangliheng/p/6094151.html 演示一下在MySQL下搭建多主一从的过程. 实验环境: 192.168.24.129:3306 192.168.24.129:3307 192.168.24.129:3308 主库操作 导出数据 分别在3306和3307上导出需要的数据库. 3306: 登录数据库: [[email protected] 3306]# mysql -uroot -poldboy123 -S /tmp/mysql3

CentOS7 下 MySQL 5.7.23 & XtraBackup 24 做数据备份——安装软件

在两台机子上同时操作下面的步骤 首先安装MySQL,从官网下载相对应版本的RPM包 mysql-community-client-5.7.23-1.el7.x86_64.rpm mysql-community-common-5.7.23-1.el7.x86_64.rpm mysql-community-libs-5.7.23-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.23-1.el7.x86_64.rpm (*解决与XtraBackup安装

Linux 6.7 安装 MySQL 8.0.16

操作系统: 2.6.32-754.10.1.el6.x86_64 MySQL版本:8.0.16 下载地址:https://dev.mysql.com/downloads/ 安装方法: 使用rpm安装 [[email protected]]# cd /opt/*******/data [[email protected]]# mkdir mysql [[email protected]]# tar xvf /var/tmp/mysql-8.0.16-1.el6.x86_64.rpm-bundle.

Linux CentOS6.5下编译安装MySQL 5.6.16【给力详细教程】

一.编译安装MySQL前的准备工作 安装编译源码所需的工具和库 [sql] view plaincopy yum install gcc gcc-c++ ncurses-devel perl 安装cmake,从http://www.cmake.org下载源码并编译安装 [sql] view plaincopy wget http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz tar -xzvf cmake-2.8.10.2.tar.gz cd 

Qt5官方demo解析集16——Chapter 2: Connecting to C++ Methods and Signals

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集15--Chapter 1: Creating a New Type 在上篇博文我们了解到如何在C++代码中将一个C++类注册为一个QML类型,并供QML文件使用.接下来这个Demo中进一步向这个PieChart中添加信号和方法供QML使用. 在项目上没有什么改变,我们直接来看代码PieChart.h: #ifndef P

CentOS 6.4下编译安装MySQL 5.6.16

一.卸载旧版本MySql 1.rpm卸载: 1> 检查安装包: rpm -qa | grep mysql 2> 普通删除: rpm -e mysql-5.6.16.rpm 3> 强力删除.如果使用上面命令删除时,提示有依赖的其他文件,则使用该命令可以对其进行强力删除. rpm -e --nodeps mysql-5.6.16.rpm 2.tar卸载: 1> 删除临时文件: make clean 2> 卸载 make uninstall 3> 删除解压文件 rm  -rf

CentOS 6.5下手动编译Apache 2.2.6 + PHP 5.3.28 + Mysql 5.6.16

很久没配置过服务器,走了不少弯路,有些参数变化,搜索到的网上文档也没有更新,故此记录自查. 版本的选择: 线上系统一个重要原则就是绝对不能用最新版本,因为没经过时间和市场的考验,安装量小,出故障后很难得到他人的帮助,如果没有独自的内核级开发能力就别当小白鼠了. 要使用当下普遍安装且稳定成熟的老版本,本次的三个版本均源自论坛.QQ群等多方调查,多家公司线上均在使用,是目前比较成熟但又不会过于老旧的"老版本". 一.准备工作: 1.禁用SeLinux (selinux可能会致使编译安装失败