MySQL 存储过程游标
简介:在本教程中,您将学习如何在存储过程中使用MySQL游标来迭代
SELECT
语句返回的结果集。
MySQL游标简介
要处理存储过程中的结果集,请使用游标。游标允许您迭代查询返回的一组行,并相应地处理每一行。 MySQL游标是只读的,不可滚动且不敏感的。- 只读:您无法通过游标更新基础表中的数据。
- 不可滚动:您只能按
SELECT
语句确定的顺序获取行。您无法以相反的顺序获取行。此外,您不能跳过行或跳转到结果集中的特定行。 - 未定型:有两种光标:未定型游标和不敏感游标。敏感光标指向实际数据,而不敏感光标使用数据的临时副本。敏感性游标比不敏感游标执行得更快,因为它不必创建临时数据副本。但是,对来自其他连接的数据所做的任何更改都将影响敏感光标正在使用的数据,因此,如果不更新敏感光标正在使用的数据,则更安全。MySQL游标是敏感的。
使用MySQL游标
首先,您必须使用以下DECLARE
语句声明游标:
DECLARE cursor_name CURSOR FOR SELECT_statement;游标声明必须在任何变量声明之后。如果在变量声明之前声明游标,MySQL将发出错误。游标必须始终与
SELECT
语句关联。
接下来,使用OPEN
语句打开游标。OPEN
语句初始化游标的结果集,因此,必须在从结果集中获取行之前调用OPEN
语句。
OPEN cursor_name;然后,使用
FETCH
语句检索光标指向的下一行,并将光标移动到结果集中的下一行。
FETCH cursor_name INTO variables list;之后,您可以在获取之前检查是否有可用的行。 最后,调用
CLOSE
语句以停用游标并释放与其关联的内存,如下所示:
CLOSE cursor_name;当光标不再使用时,您应关闭它。 使用MySQL游标时,还必须声明
NOT FOUND
处理程序以在光标找不到任何行时处理情况。因为每次调用FETCH
语句时,游标都会尝试读取结果集中的下一行。当光标到达结果集的末尾时,它将无法获取数据,并且会引发一个条件处理程序用于处理此情况。
要声明NOT FOUND
处理程序,请使用以下语法:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;这
finished
是一个变量,表示光标已到达结果集的末尾。请注意,处理程序声明必须出现在存储过程内的变量和游标声明之后。
下图说明了MySQL游标的工作原理。
MySQL游标实例
我们将开发一个存储过程,用于构建示例数据库employees
中表中 所有员工的电子邮件列表。
首先,声明一些变量,一个用于循环遍历员工电子邮件的游标和一个NOT FOUND
处理程序:
DECLARE finished INTEGER DEFAULT 0; DECLARE email varchar(255) DEFAULT ""; -- declare cursor for employee email DEClARE email_cursor CURSOR FOR SELECT email FROM employees; -- declare NOT FOUND handler DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;接下来,
email_cursor
使用以下OPEN
语句打开:
OPEN email_cursor;然后,迭代电子邮件列表,并连接每个电子邮件用分号(;)分隔的所有电子邮件:
get_email: LOOP FETCH email_cursor INTO v_email; IF v_finished = 1 THEN LEAVE get_email; END IF; -- build email list SET email_list = CONCAT(v_email,";",email_list); END LOOP get_email;之后,在循环内部,我们使用
v_finished
变量来检查列表中是否有电子邮件来终止循环。
最后,使用以下CLOSE
语句关闭游标:
CLOSE email_cursor;
build_email_list
存储过程如下:
DELIMITER $$ CREATE PROCEDURE build_email_list ( INOUT email_list VARCHAR ( 4000 ) ) BEGIN DECLARE v_finished INTEGER DEFAULT 0; DECLARE v_email VARCHAR ( 100 ) DEFAULT ""; DECLARE email_cursor CURSOR FOR SELECT email FROM employees; DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1; OPEN email_cursor; get_email :LOOP FETCH email_cursor INTO v_email; IF v_finished = 1 THEN LEAVE get_email; END IF; SET email_list = CONCAT( v_email, ";", email_list ); END LOOP get_email; CLOSE email_cursor; END $$ DELIMITER ;您可以
build_email_list
使用以下脚本测试存储过程:
SET @email_list = ""; CALL build_email_list(@email_list); SELECT @email_list;在本教程中,我们向您展示了如何使用MySQL游标迭代结果集并相应地处理每一行。