本节要点

游标简介
游标的使用步骤
一个游标使用的示例
游标的优缺点

游标简介

先来看下面一个SQL:

UPDATE student SET age = age + 1;

执行这个SQL时,实际上数据库是将students表中所有记录的age字段加1。也就是说,数据库将students表中所有学生这个集合中的年龄全部加了1岁。

可有时候,我们针对students表中所有学生这个集合中的不同学生,可能有不同的操作。比如说,一年级一班的同学,每人加1岁;如果性别为女生或姓张的同学,每人加2岁。这样的逻辑,使用SQL语句来写,可能也能写。但SQL稍显复杂。

上面的场景还好。假如说,有更复杂的需求,使用单个SQL语句来编写可能就比较复杂了,而且要求我们对数据库中的每一行,都做相应的特殊处理,这样实现起来就比较难。

实际上,SQL语言提供了游标的功能,让我们能依次处理表中的每条记录。

游标类似于指针,从集合中依次提取单条记录,直至提取完最后一条,而且这个指针,每一次循环只指向一个单行。

这就给了我们针对表中每一行实现特有的逻辑的方法。

我们可以在存储过程、函数、触发器中使用游标。所以,游标的使用场景还是挺广的。

游标的使用步骤

在使用游标时,一般会经过下面四个步骤:

第一步:定义游标

DECLARE 游标名称 CURSOR FOR SELECT子句;

第二步:打开游标

OPEN 游标名称

第三步:使用游标

FETCH 游标名称 INTO 变量名1,变量名2,变量名3[,…]

第四步:关闭游标

CLOSE 游标名称

一个游标使用的示例

下面这个例子,从student表中,将成绩在90分以上的学生编号和学生姓名查询出来并返回,并没有做其他更复杂的操作。

实际上,我们WHILE循环的内部,针对每一条记录,完成需要的复杂操作。

这里只是举个例子,来说明游标是如何使用的:

CREATE PROCEDURE cursor_student()
BEGIN
    DECLARE v_student_id varchar(50);
    DECLARE v_student_name varchar(100);
    DECLARE done INT DEFAULT false;
    DECLARE mycursor CURSOR FOR SELECT student_id,student_name FROM student WHERE score >= 90;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
    OPEN mycursor;
    FETCH mycursor INTO v_student_id,v_student_name;
    WHILE(NOT done)
    DO
        SELECT v_student_id,v_student_name;
        FETCH mycursor INTO v_student_id,v_student_name;
    END WHILE;
    CLOSE mycursor;
END;

游标的优缺点

当然了,游标也有它自己的优缺点。对于表的操作,它提供了一种除集合操作外的行操作方式。这一点在逻辑比较复杂的时候,非常有用。

但因为游标是对表中每一行单独做操作,所以在数据量比较大的时候,可能会造成内存不足,而且很多时候,性能比较差。

一般来说,我们不建议使用循环次数在1万以上的游标操作。对于循环次数太多的游标操作,建议将业务需求转换为多个集合操作来实现。

picture loss