MySQL 提供三種循環語句,各有適用場景。本文通過完整可執行範例,詳細講解語法、標籤跳出機制、變數控制與常見陷阱。
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_test_while`$$
CREATE PROCEDURE `sp_test_while`(
IN p_number INT, -- 循環上限
IN p_startid INT -- 起始值
)
BEGIN
DECLARE v_val INT DEFAULT 0;
SET v_val = p_startid;
outer_label: BEGIN -- 定義標籤塊
WHILE v_val <= p_number DO
SET v_val = v_val + 1;
IF v_val = 100 THEN
LEAVE outer_label; -- 跳出標籤塊,後續標籤內代碼不再執行
END IF;
END WHILE;
SELECT '我是 while 外,outer_label 內的 SQL'; -- 不會執行
END outer_label;
SELECT CONCAT('test', v_val) AS tname; -- 會執行
END$$
DELIMITER ;
CALL sp_test_while(1000, 0);
關鍵點:
LEAVE label 跳出的是 標籤塊,而非僅循環體DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_testloop`$$
CREATE PROCEDURE `sp_testloop`(
IN p_number INT,
IN p_startid INT
)
BEGIN
DECLARE v_val INT DEFAULT 0;
SET v_val = p_startid;
loop_label: LOOP
SET v_val = v_val + 1;
IF v_val > p_number THEN
LEAVE loop_label;
END IF;
END LOOP;
SELECT CONCAT('testloop_', v_val) AS tname;
END$$
DELIMITER ;
CALL sp_testloop(1000, 0);
適用場景:循環次數動態決定、需在循環體中間多點判斷退出。
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_test_repeat`$$
CREATE PROCEDURE `sp_test_repeat`(
IN p_number INT,
IN p_startid INT
)
BEGIN
DECLARE v_val INT DEFAULT 0;
SET v_val = p_startid;
REPEAT
SET v_val = v_val + 1;
UNTIL v_val > p_number -- 注意:UNTIL 後**不加分號**
END REPEAT;
SELECT CONCAT('test', v_val) AS tname;
END$$
DELIMITER ;
CALL sp_test_repeat(1000, 0);
語法陷阱:UNTIL condition 後**不能加分號**,否則報語法錯誤。
| 循環類型 | 判斷時機 | 最少執行次數 | 典型場景 |
|---|---|---|---|
| WHILE | 迭代前 | 0 | 已知上限、預先檢查條件 |
| LOOP | 內部手動 | 1 | 複雜中斷邏輯、多退出點 |
| REPEAT | 迭代後 | 1 | 至少執行一次、後置條件 |
outer: BEGIN
inner: LOOP
-- ...
IF condition THEN LEAVE outer; END IF; -- 直接跳出外層
END LOOP inner;
END outer;
善用標籤實現多層流程控制,避免旗標變數汙染邏輯。