zoukankan      html  css  js  c++  java
  • 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;

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

     

  • 相关阅读:
    总结c#和javascript中常见的相关的"空"
    javascript从未如此流行(JavaScript has never been so popular .)
    解决ajax调用中ie的缓存问题
    《.NET框架程序设计》第5章 基元类型、引用类型与值类型
    DataTable复制到新的DataTable并筛选
    《.NET框架程序设计》第1章 .NET开发平台体系架构 读后感
    《.NET框架程序设计》第4章 类型基础 读后感
    《.NET框架程序设计》第2章 第3章 读后感
    《道德经》程序员版第四十二章
    数据库设计总结
  • 原文地址:https://www.cnblogs.com/xkxf/p/8916426.html
Copyright © 2011-2022 走看看