MySQL必知必会——第二十四章使用游标

使用游标

本章将讲授什么是游标以及如何使用游标。

游标

MySQL检索操作返回一组称为结果集的行。这组行都是与SQL语句相匹配的行。使用简单的SELECT语句,没有办法得到第一行、下一行或前十行,也不存在每次仅修改结果集中某行的办法。

有时,需要在检索出来的行中前进或后退一行或多行。我们可以使用游标(cursor),它是一个存储在MySQL服务器上的数据库查询,并非一条SELECT语句,而是一个SELECT语句检索出的结果集。在存储了游标后,应用程序可以根据需要滚动或浏览其中的数据。

只能用于存储过程 MySQL游标只能用于存储过程(和函数)。


使用游标

使用游标需要几个步骤:

  1. 使用游标前,必须声明(定义)它。 此时并未检索数据,只是定义使用的SELECT语句。
  2. 声明后,必须打开游标以供使用。 此时使用定义的SELECT语句进行实际检索。
  3. 对于填有数据的游标,根据需要取出(检索)各行。
  4. 结束游标使用时,必须关闭游标。

声明游标后,可根据需要频繁地打开和关闭游标。游标打开后,可根据需要频繁地执行取操作。

创建游标

游标用DECLARE语句创建(MySQL必知必会——第二十三章使用存储过程)。DECLARE命名游标,并定义相应的SELECT语句。

定义名为ordernumbers的游标:

mysql> DELIMITER //
mysql> CREATE PROCEDURE processorders()
    -> BEGIN
    ->     DECLARE ordernumbers CURSOR
    ->     FOR
    ->     SELECT order_num FROM orders;
    -> END //
Query OK, 0 rows affected (0.04 sec)

mysql> DELIMITER ;

DECLARE语句用来定义和命名游标。存储过程处理完成后,游标就消失。

DELIMITER DELIMITER修改了命令行的默认语句结束符,若非命令行客户端,需将DELIMITER行删除,并且END后//改;,详情见MySQL必知必会——第二十三章使用存储过程

打开和关闭游标

游标用OPEN CURSOR语句来打开:

OPEN ordernumbers;

处理OPEN语句时执行查询,存储检索出的数据以供浏览和滚动。

游标处理完成后可使用CLOSE语句关闭游标:

CLOSE ordernumbers;

CLOSE释放游标使用的所有内部内存和资源,因此每个游标不再需要时都应该关闭。

游标关闭后,需要重新打开才可使用。但声明过的游标,无需再次声明。

  • 隐式关闭 如果不明确关闭游标,MySQL将在END语句时自动关闭游标。

使用游标数据

游标打开后,可以使用FETCH语句分别访问它的每一行。FETCH指定检索什么数据,检索出来的数据存储在什么地方。它还向前移动游标中的内部行指针,使下一条FETCH语句检索下一行。

从游标中检索 单个行

CREATE PROCEDURE processorders()
BEGIN

    -- Declare local variables
    DECLARE o INT;

    -- Declare the cursor
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM orders;

    -- Open the cursor
    OPEN ordernumbers;

    -- Get order number
    FETCH ordernumbers INTO o;

    -- Close the cursor
    CLOSE ordernumbers;

END;

此语句中,FETCH用来检索当前行的order_num列(自动从第一行开始)到名为o的局部声明的变量中。

从游标中 循环检索 所有行:

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

此语句与前一个不同的是,FETCH是在REPEAT内,因此它反复执行直到done为真(由UNTIL done END REPEAT;规定)。done用DEFAULT 0语句默认为假,并且在结束时使用以下语句设置为真:

DELCARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

此语句定义了一个CONTINUE HANDLER,它是在条件出现时被执行的代码。SQLSTATE '02000’是一个未找到条件,但REPEAT由于没有更多行供循环而继续时,出现这个条件。

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

调用此存储过程将定义几个变量和一个CONTINUE HANDLER,定义并打开一个游标,重复读取所有行,然后关闭游标。

  • 重复或循环? 除了REPEAT语句外,MySQL还支持循环语句,可用来重复执行代码,直到使用LEAVE语句手动退出。

综合样例:

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(0, 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;

此样例,我们使用变量t来存储每个订单的合计。此存储过程还在运行中创建了一个新表,名为ordertotals,用来存储结果。FETCH取每个order_num,然后用CALL执行另一个存储过程(上章的样例)来计算每个订单带税的合计。最后用INSERT保存每个订单的订单号和合计。

可通过查询存储结果的新表,来查看数据。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
MySQL游标使用可以通过以下步骤进行: 1. 声明游标使用DECLARE语句声明游标,并指定游标的名称和SELECT语句。 2. 打开游标使用OPEN语句打开游标,将查询结果集绑定到游标上。 3. 获取游标数据:使用FETCH语句从游标中获取一行数据,并将其存储在变量中供后续处理。 4. 处理游标数据:可以在循环中使用游标数据进行各种操作,比如输出、计算等。 5. 关闭游标使用CLOSE语句关闭游标,释放资源。 在MySQL中,当游标溢出时会引发预定义的NOT FOUND错误。为了处理这种情况,可以使用DECLARE CONTINUE HANDLER语句来定义一个事件,当引发NOT FOUND错误时,可以在事件中修改一个标志变量的值,以便在循环中判断是否继续执行。 例如,可以使用以下代码来处理游标溢出的情况: ``` DECLARE done BOOLEAN DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT * FROM table; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP FETCH cur INTO ...; -- 获取游标数据并存储在变量中 IF done THEN LEAVE read_loop; -- 如果标志变量为TRUE,则跳出循环 END IF; -- 处理游标数据 ... END LOOP; CLOSE cur; ``` 此外,如果需要在查询中使用参数,可以使用PREPARE语句和EXECUTE语句来动态构建和执行带有参数的查询语句。首先使用PREPARE语句准备查询语句,然后使用EXECUTE语句执行查询,并通过USING子句传递参数。 例如,可以使用以下代码来执行带有参数的查询: ``` SET @condition1 = ...; -- 设置参数的值 SET @sqlStr = 'SELECT * FROM table WHERE condition1 = ?'; PREPARE stmt FROM @sqlStr; EXECUTE stmt USING @condition1; DEALLOCATE PREPARE stmt; -- 释放资源 ``` 这样就可以动态地构建和执行带有参数的查询语句了。 #### 引用[.reference_title] - *1* [MySQL游标使用](https://blog.csdn.net/weixin_44377973/article/details/103767867)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [MySql游标的定义与使用方式](https://blog.csdn.net/liguo9860/article/details/50848216)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霖行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值