MySQL里的Cursor和Fetch是什么?新手一看就懂的教程

ChatGPT2026-04-24 11:38:4038

温馨提示:在 ChatGPT 官网(www.chatgpt.com)使用 GPT-5.5、ChatGPT-Image-2 等模型时,需要 ChatGPT Plus 或更高等级的会员权限。如需购买账号或充值会员,请扫码添加我们客服咨询。

MySQL中的Cursor(游标)是一种数据库对象,用于逐行处理查询结果集,而不是一次性返回所有数据。**核心作用**:当需要逐行遍历并处理SELECT返回的多条记录时使用(如对每行执行复杂计算、更新等操作)。,**Cursor使用步骤**:,1. **声明**:DECLARE cursor_name CURSOR FOR SELECT ...,2. **打开**:OPEN cursor_name,3. **读取**:FETCH cursor_name INTO variable1, variable2,4. **关闭**:CLOSE cursor_name,**FETCH本质**:游标的“指针移动指令”,执行FETCH时,游标从当前位置移到下一行,并将该行的指定列赋值给对应的变量,通常在循环中配合NOT FOUND条件使用,直到所有行被取完。,**典型场景**:存储过程或函数中,需要基于数据逐行执行逻辑(如批量更新、生成动态SQL)。,**注意**:游标会消耗资源,仅当无法用纯SQL(如JOIN/子查询)实现时使用。

本文目录导读:

  1. 先从一个小故事开始
  2. 为什么要有游标?
  3. 怎么在MySQL里用游标?
  4. 一个完整的例子
  5. 给新手的一些建议
  6. 总结一下

你好,欢迎来到今天的教程,很多刚开始学MySQL的朋友,听到“Cursor”(游标)和“Fetch”(提取)这两个词,可能会觉得有点糊涂,感觉它们像是什么很高级、很难懂的东西。

其实不是这样的,今天我们就来说清楚,这两个东西到底是怎么回事,以及我们什么时候会用到它们,我会用最简单的话来讲,保证你能听懂。

先从一个小故事开始

想象一下,你有一个大箱子,箱子里有很多卡片,每张卡片上都写着一个名字,你的任务是,一张一张地看这些卡片,然后做点什么事,比如把名字念出来。

正常情况下,我们写SQL查询,就像是把这个大箱子整个端起来,一下把所有卡片都倒出来,然后你得到一个结果集,里面是所有名字。

但有时候,我们不想一下倒出来,我们想一张一张地拿,先把第一张拿出来,看看,处理一下,再拿第二张,一张接着一张,直到全部拿完。

这个“一张一张拿卡片”的过程,就是游标做的事情。 而“拿出一张卡片”这个动作,Fetch

为什么要有游标?

你可能会问:“我把卡片全倒出来,然后用程序一条条处理,不也是一样的吗?”

在某些情况下,是的,有几种情况,用游标会更方便。

  1. 你需要一行一行地处理数据。 你有一个订单表,你不仅要把订单信息查出来,还要根据每个订单里的金额,去更新另一个客户表的“总消费”字段,如果用普通的查询,你很难在查询过程中,一边查,一边去做更新操作。

  2. 你的程序需要“停下来”思考。 你的程序在处理完一行数据后,需要做一些复杂的计算或者判断,这些计算和判断,可能取决于它上一行处理的结果,只有一行行地拿,一行行地处理,才能做到这一点。

  3. 处理不了的大查询。 如果你用普通的SELECT语句,一次查出几百万行数据,可能会让你的程序内存爆掉,而用游标,你可以每次只取一行,内存压力就小很多。

简单说,游标就是一个指针,它指向你查询结果里的某一行。 一开始,它指向第一行之前,你执行一次Fetch,它就往下走一行,指向下一行,并把那一行的数据取出来给你。

怎么在MySQL里用游标?

在MySQL里,使用游标有固定的几个步骤,记住了,其实不难。

第一步:声明(Declare)游标

这一步,就像是给你的“卡片箱”起个名字,并且告诉MySQL,你想从哪个箱子里拿卡片。

DECLARE my_cursor CURSOR FOR
SELECT name, age FROM users WHERE age > 18;

这句代码的意思是:我声明了一个叫 my_cursor 的游标,它会去执行后面的那个查询,这个查询会拿到所有年龄大于18岁的用户的名字和年龄。

第二步:打开(Open)游标

声明只是定义,还没真开始干活,打开游标,才是真正去执行那个查询,准备好“卡片箱”。

OPEN my_cursor;

做完这一步,游标就准备好了,可以开始取数据了。

第三步:提取(Fetch)数据

这就是最关键的“拿卡片”的动作,你需要用变量来接收你拿到的数据。

FETCH my_cursor INTO v_name, v_age;

这句代码的意思是:从 my_cursor 这个游标里,取下一行的数据,取到的 name 放到 v_name 这个变量里,取到的 age 放到 v_age 这个变量里,然后你就可以用 v_namev_age 去做你想做的事了。

注意,你需要有提前定义好的变量,v_namev_age,它们的类型要和你的表字段匹配。DECLARE v_name VARCHAR(100);

第四步:处理完数据后,关闭(Close)游标

用完了,记得把“卡片箱”关上,释放资源。

CLOSE my_cursor;

一个完整的例子

下面是一个在存储过程里使用游标的完整例子,这个例子很简单,就是遍历所有用户,然后把他们名字里加个“先生”的称呼,更新到另一个字段里去。

-- 先创建一个存储过程
DELIMITER $$
CREATE PROCEDURE process_users()
BEGIN
    -- 声明变量,用来接收游标取出来的数据
    DECLARE v_id INT;
    DECLARE v_name VARCHAR(100);
    DECLARE done INT DEFAULT FALSE;
    -- 声明游标
    DECLARE user_cursor CURSOR FOR
    SELECT id, name FROM users;
    -- 声明一个处理程序,当游标没有数据可以取了(NOT FOUND)的时候,就把done变量设为TRUE
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    -- 打开游标
    OPEN user_cursor;
    -- 开始循环取数据
    read_loop: LOOP
        -- 取下一行数据
        FETCH user_cursor INTO v_id, v_name;
        -- 如果done为TRUE,说明取完了,就跳出循环
        IF done THEN
            LEAVE read_loop;
        END IF;
        -- 在这里处理每一行的数据
        -- 更新该用户的称呼字段
        UPDATE users SET title = CONCAT(v_name, '先生') WHERE id = v_id;
    END LOOP;
    -- 关闭游标
    CLOSE user_cursor;
END$$
DELIMITER ;

我来解释一下这个例子里的几个关键点:

  1. DECLARE done INT DEFAULT FALSE;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 这一段,很重要,游标提取数据时,如果取到最后一行之后,再取就会报错,这个 CONTINUE HANDLER 就是用来处理这个错误的,它会捕捉到“没了”这个信号,然后把 done 设为真,这样我们的循环就知道可以停止了。
  2. 循环里的 LOOP ... END LOOPLEAVE read_loop 是最简单的循环方式。
  3. FETCH 之后,我们做了一件事:UPDATE users SET title = ...,这就是“一行行处理”的体现。

给新手的一些建议

  1. 别随便用游标。 虽然我们讲了它是什么和怎么用,但新手很容易犯的一个错就是:遇到点复杂问题,就想用游标,很多时候,用 JOIN 连接表,或者用 UPDATE ... JOIN 这种一次性操作,都比游标快得多,游标速度慢,因为它是一行行处理的,只有在实在没办法用一条SQL解决,或者必须一行行处理的时候,才考虑用游标。
  2. 先想明白你的逻辑。 在你写代码之前,先在纸上或者脑子里过一遍:你想要的流程是不是真的需要“一行行看,一行行做”?大多数情况都不是。
  3. 测试的时候要小心。 在写存储过程时,特别是里面包含 UPDATEDELETE 操作时,先在测试数据库里跑一遍,万一写错,可能会把整个表的数据改坏了,你可以在一个小的测试表上先试。
  4. 理解“指针”的概念。 多想想那个“一张张拿卡片”的例子,游标就像你的手指,一直指着当前拿到的卡片。FETCH 一次,手指就往下移一点。
  5. 多用变量。 游标取出来的数据,放到变量里,你才能操作它,先想好你需要哪些变量,记好它们的类型。

总结一下

  • 游标(Cursor):一个可以一行行指向你查询结果集的指针。
  • 提取(Fetch):用游标获取当前指向的那一行数据,并把数据存到变量里的动作。
  • 使用步骤:声明 -> 打开 -> 循环Fetch -> 处理数据 -> 关闭。
  • 新手原则:少用游标,多想想能不能用一条普通SQL搞定,如果必须用,就按步骤来,别忘了解释 NOT FOUND 的处理。

好了,希望今天这篇教程能帮你搞清楚MySQL里的游标和Fetch,第一次接触可能会觉得有点绕,但多写几次,把上面的例子自己敲一遍,感觉就会来了,祝你学习愉快!

温馨提示:在 ChatGPT 官网(www.chatgpt.com)使用 GPT-5.5、ChatGPT-Image-2 等模型时,需要 ChatGPT Plus 或更高等级的会员权限。如需购买账号或充值会员,请扫码添加我们客服咨询。

本文链接:https://www.lexitong.com/ai/176.html

逐行处理结果集mysql cursor fetch

相关文章

网友评论