在编程中,循环是一种常见的结构,它允许重复执行一系列指令,直到满足某个条件。MySQL数据库也提供了一种机制,允许对查询返回的每一行数据执行一系列指令,这就是游标。游标可以针对SQL查询返回的行执行一组指令。
MySQL游标具有以下特性:
要创建MySQL游标,需要使用DECLARE、OPEN、FETCH和CLOSE语句。
DECLARE语句可以声明变量、游标和处理器。声明顺序如下:
首先必须声明至少一个变量,稍后将与FETCH语句一起使用。
SQL
DECLARE <variable_name> <variable_type>
声明变量。
声明游标时,必须附加一个SELECT语句。任何有效的SELECT语句都可以。还必须声明至少一个游标。
SQL
DECLARE <cursor_name> CURSOR FOR <select_statement>
为SELECT语句声明游标。
还必须声明一个NOT FOUND处理器。当游标迭代到最后一行时,会触发一个条件,该条件将由NOT FOUND处理器处理。根据需要,还可以声明其他处理器。例如:
SQL
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
使用NOT FOUND处理器。
OPEN语句初始化DECLARE游标语句的结果。
SQL
OPEN <cursor_name>
OPEN语句语法。
FETCH语句作为迭代器。它从游标声明中的SELECT语句关联的行中获取下一行。
SQL
FETCH <cursor_name> INTO <variable_list>
FETCH语句语法。
<variable_list>是一个或多个之前声明的变量。
SQL
FETCH <cursor_name> INTO a, b, c
示例变量列表。
如果存在下一行,则变量存储它;否则,将发生SQLSTATE为'02000'的No Data条件。可以使用NOT FOUND处理器处理此SQLSTATE。
此语句关闭OPEN语句中打开的游标。
SQL
CLOSE <cursor_name>
CLOSE语句语法。
准备好开始使用MySQL游标了吗?首先,需要创建一个数据库和一个表。在这个演示中,将使用CSV文件中的数据填充一个表。
将创建一个游标,用于:
以下是实现此目的的MySQL过程。
SQL
DELIMITER $$
CREATE PROCEDURE cursordemo(INOUT average_goals FLOAT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE matches int DEFAULT (0);
DECLARE goals int DEFAULT (0);
DECLARE half_time_goals INT;
DECLARE team_cursor CURSOR FOR SELECT HTHG FROM epl.football WHERE (FTR = "H");
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN team_cursor;
teams_loop: LOOP
FETCH team_cursor INTO half_time_goals;
IF done THEN
LEAVE teams_loop;
END IF;
SET goals = goals + half_time_goals;
SET matches = matches + 1;
END LOOP teams_loop;
SET average_goals = goals / matches;
CLOSE team_cursor;
END $$ DELIMITER;
MySQL过程
MySQL中的过程类似于包含一系列指令的容器。过程用MySQL编写并存储在数据库中。在过程中定义游标,因为过程是可重用的。执行上面的SQL过程将把过程存储在数据库中。可以使用其名称调用过程,如下所示:
SQL
SET @average_goals = 0.0;
CALL cursordemo(@average_goals);
SELECT @average_goals;
执行刚刚创建的过程。
此操作的输出为:
1.080954670906067
从示例中可以看出,使用SELECT AVG(HTHG) FROM epl.football WHERE (FTR="H");这样的SQL查询可以实现相同的结果。最好只在处理单行时使用游标。例如完整性检查、索引重建。请注意,每次游标获取一行,都会进行一轮网络往返。因此,根据操作的大小,它可能会减慢MySQL服务器。