MySQL基本函数、循环跳出与游标使用详解
SQL99的NATURALJOIN、USING及全文检索(需fulltext索引和ngram解析器)可简化查询;MySQL基本函数涵盖字符串与日期处理;存储过程通过REPEAT、WHILE、LOOP实现循环,使用LEAVE跳出、ITERATE继续下次循环;游标逐条处理结果集,需配合CONTINUEHANDLER声明以正常结束循环。
SQL99语法新特性
SQL99 中几个常用的小特性,在日常查询中能显著简化操作,减少重复代码。
- NATURAL JOIN(自然连接):自动匹配两张表中所有同名字段,执行等值连接。省去手动编写 ON 条件的步骤。
select a.dept_id,b.dept_id from A a NATURAL JOIN B b
- USING:当两张表存在相同字段名(例如都包含 dept_id)时,通过 USING 指定该字段即可,语法更为简洁。
select a.dept_id,b.dept_id from A a join B b USING(dept_id)
- match() Against() 全文检索
- 查询字段必须创建为 fulltext 索引。
- match 默认不支持中文检索,添加索引时需指定解析器:
WITH PARSER ngram。 - 传统 LIKE 在此场景下容易导致索引失效,全文检索性能更优。
- 可通过
SHOW VARIABLES LIKE 'ngram_token_size'查看分词设置,也可调整配置。
SELECT id_, pat_name, id_card_no, phone_ FROM `inspect_meal_appointment_record` WHERE MATCH ( pat_name ) Against ('张三' );
CREATE FULLTEXT INDEX ind ON inspect_meal_appointment_record (pat_name) WITH PARSER ngram;


基本函数
MySQL 内置的基本函数覆盖字符串处理、日期计算等常见场景。下图为常用函数速查汇总,适合收藏备用。

循环
存储过程中,循环是核心控制结构。以下通过存储过程示例,介绍三种循环方式:REPEAT、WHILE 和 LOOP,以及跳出循环的 LEAVE 和继续下一次迭代的 ITERATE。
REPEAT 循环

CREATE DEFINER=`root`@`localhost` PROCEDURE `repeatTest`()
BEGIN
DECLARE nums INT DEFAULT 1;
REPEAT
SET nums = nums + 1;
UNTIL nums >= 10
END REPEAT;
SELECT nums;
END
WHILE 循环

CREATE DEFINER=`root`@`localhost` PROCEDURE `whileTest`()
BEGIN
DECLARE nums INT DEFAULT 1;
WHILE nums <= 10 DO
SET nums = nums + 1;
END WHILE;
SELECT nums;
END
LOOP 循环

CREATE DEFINER=`root`@`localhost` PROCEDURE `loopTest`()
BEGIN
DECLARE nums INT DEFAULT 1;
test_label: LOOP
SET nums = nums + 1;
IF nums >= 110 THEN
LEAVE test_label;
END IF;
END LOOP test_label;
SELECT nums;
END
LEAVE 跳出循环
LEAVE 既可用于循环,也可用于单独的 BEGIN…END 块。以下示例在 WHILE 循环中通过 LEAVE 提前终止执行。

CREATE DEFINER=`root`@`localhost` PROCEDURE `leaveTest`()
BEGIN
DECLARE nums INT DEFAULT 1;
while_label: WHILE TRUE DO
IF nums > 10 THEN
LEAVE while_label;
END IF;
SET nums = nums + 1;
END WHILE;
SELECT nums;
END
ITERATE 执行下一次循环
ITERATE 相当于 Java 中的 continue,仅能用于循环内部。以下 LOOP 循环中,当 nums < 10 时直接跳至下一次迭代;仅在 nums 处于 10~15 之间时累加并继续执行。

CREATE DEFINER=`root`@`localhost` PROCEDURE `ITERATETest`()
BEGIN
DECLARE nums INT DEFAULT 1;
test_label: LOOP
SET nums = nums + 1;
IF nums < 10 THEN
ITERATE test_label;
ELSEIF nums > 15 THEN
LEAVE test_label;
END IF;
END LOOP test_label;
SELECT nums;
END
游标
游标在存储过程中用于逐条处理查询结果集。以下为数据迁移时的实际应用:遍历分组后的结果,对每个套餐 ID 更新对应的类型标签表。
CREATE DEFINER=`inspect-v2-develop`@`%` PROCEDURE `updateTypeLabel`()
COMMENT '数据迁移,储存过程'
BEGIN
DECLARE s INT DEFAULT 0;
DECLARE mealId VARCHAR(64);
DECLARE num INT DEFAULT 0;
DECLARE list CURSOR FOR
SELECT deploy_meal_id, COUNT(deploy_meal_id)
FROM inspect_meal_deploy
WHERE is_deleted = '0'
GROUP BY deploy_meal_id;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s = 1;
OPEN list;
FETCH list INTO mealId, num;
WHILE s <> 1 DO
IF num >= 1 THEN
UPDATE inspect_meal_type_label
SET meal_deploy_id = (
SELECT id_ FROM inspect_meal_deploy
WHERE is_deleted = '0' AND deploy_meal_id = mealId
LIMIT 1
)
WHERE meal_id = mealId AND is_deleted = '0';
END IF;
FETCH list INTO mealId, num;
END WHILE;
CLOSE list;
END
关键代码 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s = 1; 声明了一个句柄,相当于存储过程中的异常处理器。CONTINUE 表示触发句柄后继续执行后续语句(而非 EXIT 直接退出最近的 BEGIN…END 块)。SQLSTATE '02000' 对应“未找到记录”,即游标遍历完所有行后执行 SET s = 1,使 WHILE 条件失效,从而正常结束循环。
注意:句柄声明必须位于游标之后,否则会报错 ERROR 1338 (42000): Cursor declaration after handler declaration,声明顺序不可颠倒。
总结
SQL99 语法中的 NATURAL JOIN、USING 和全文检索可让查询更简洁高效;MySQL 的循环与游标是存储过程中处理复杂业务逻辑的重要工具。掌握这些基础用法,足以应对日常存储过程的编写需求。
