跳转至

游标

有时,需要在检索出来的行中前进或后退一行或多行 - 游标是一个存储在MySQL服务器上的数据库查询 - 它不是一条SELECT语句,而是被该语句检索出来的结果集 - 在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据 游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改

MySQL的游标只能用于存储过程和函数

使用游标

  • 几个明确的步骤:
    • 声明(定义)游标
    • 一旦声明后,必须打开游标以供使用
      • 这个过程用前面定义的SELECT语句把数据实际检索出来
    • 对于填有数据的游标,根据需要取出(检索)各行
    • 在结束游标使用时,必须关闭游标

创建游标

  • 游标使用DECLARE语句创建,并且定义相应的SELECT语句,根据需要带WHERE和其他字句
  • 在声明时即确定游标中包含的数据
    -- 此处仅创建游标
    CREATE PROCEDURE processorders()
    BEGIN
        DECLARE ordernumbers CURSOR
        FOR
        SELECT order_num FROM orders;
    END;
    

打开和关闭游标

  • 打开游标:OPEN cursor_name;
    • 在处理OPEN语句时执行查询,存储检索出的数据以供浏览和滚动
  • 关闭游标:CLOSE cursor_name;
    • CLOSE释放游标使用的所有内部内存和资源,因此在每个游标不在需要时都应该关闭

      在一个游标关闭后,如果没有重新打开,则不能使用它 但是,声明过的游标无需再次声明,使用OPEN语句直接打开,即可使用

隐含关闭:如果不明确关闭游标,则MySQL将会在到达END语句时自动关闭

游标数据的使用

  • 一个游标打开后,可以使用FETCH语句分别访问他的每一行
    • FETCH指定检索什么数据,检索出来的数据存储在什么地方
  • 从游标中检索单个行
    create procedure processorders()
    begin
        DECLARE done BOOLEAN DEFAULT 0;
        DECLARE o INT;
    
        declare ordernumbers cursor
        for
        select order_num from orders;
    
        open ordernumbers;
    
        FETCH ordernumbers INTO o;
    
        close ordernumbers;
    end;
    
  • 循环检索数据,从第一行到最后一行
    create procedure processorders()
    begin
        DECLARE done BOOLEAN DEFAULT 0;
        DECLARE o INT;
    
        declare ordernumbers cursor
        for
        select order_num from orders;
    
        -- declare continue handler
        DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
    
        open ordernumbers;
    
        REPEAT
            FETCH ordernumbers INTO o;
        UNTIL done 
        END REPEAT;
    
        close ordernumbers;
    end;
    
    • 本例中的FETCH语句在REPEAT中,它将反复执行直到done为真
    • DECLARE done BOOLEAN DEFAULT 0;
      • 用默认值0为done赋值
    • DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

DECLARE语句的次序: DECLARE语句定义的局部变量必须定义在任意游标或句柄之前定义,而句柄必须在游标之后定义

通常REPEAT语句的语法使它更适合于对游标进行循环,同时,也支持使用它来重复执行代码,直到使用LEAVE语句手动退出为止

终版代码

create procedure processorders()
begin
    DECLARE done BOOLEAN DEFAULT 0;
    DECLARE o INT;
    DECLARE t DECIMAL(8,2);

    declare ordernumbers cursor
    for
    select order_num from orders;

    -- declare continue handler
    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 ordernumbers INTO o;
        CALL ordertotal(o, 1, t);
        INSERT INTO ordertotals(order_num, total)
        VALUES(o,t);
    UNTIL done END REPEAT;

    close ordernumbers;
end;