| 循環類型 | 判斷時機 | 適用場景 | 跳出關鍵字 |
|---|---|---|---|
| WHILE | **前置判斷** | 已知次數或條件預檢 | LEAVE label |
| LOOP | **無條件** (需內部 LEAVE) | 複雜邏輯、多條件退出 | LEAVE label |
| REPEAT | **後置判斷** (UNTIL) | 至少執行一次 | UNTIL condition |
DELIMITER $$
CREATE PROCEDURE sp_test_while(IN p_max INT, IN p_start INT)
BEGIN
DECLARE v_val INT DEFAULT p_start;
outer_label: BEGIN
WHILE v_val <= p_max DO
SET v_val = v_val + 1;
IF v_val = 100 THEN
LEAVE outer_label; -- 跳出標籤塊,後續 SELECT 不執行
END IF;
END WHILE;
SELECT '我在 outer_label 內,LEAVE 後不會執行';
END outer_label;
SELECT CONCAT('test', v_val) AS tname; -- 正常輸出
END$$
DELIMITER ;
CALL sp_test_while(1000, 0);
關鍵點:LEAVE label 跳出的是**標籤塊**,而非僅循環體。標籤可標註 BEGIN...END、LOOP、WHILE、REPEAT。
DELIMITER $$
CREATE PROCEDURE sp_test_loop(IN p_max INT, IN p_start INT)
BEGIN
DECLARE v_val INT DEFAULT p_start;
loop_label: LOOP
SET v_val = v_val + 1;
IF v_val > p_max THEN
LEAVE loop_label;
END IF;
END LOOP;
SELECT CONCAT('testloop_', v_val) AS tname;
END$$
DELIMITER ;
CALL sp_test_loop(1000, 0);
DELIMITER $$
CREATE PROCEDURE sp_test_repeat(IN p_max INT, IN p_start INT)
BEGIN
DECLARE v_val INT DEFAULT p_start;
REPEAT
SET v_val = v_val + 1;
UNTIL v_val > p_max -- 注意:UNTIL 後**不加分號**
END REPEAT;
SELECT CONCAT('test', v_val) AS tname;
END$$
DELIMITER ;
CALL sp_test_repeat(1000, 0);
loop_label: LOOP
SET v_val = v_val + 1;
IF v_val % 2 = 0 THEN
ITERATE loop_label; -- 跳過本次剩餘邏輯,直接下一輪
END IF;
-- 只處理奇數
INSERT INTO log_table VALUES (v_val);
IF v_val > 100 THEN LEAVE loop_label; END IF;
END LOOP;
;。UNTIL condition END REPEAT;。BEGIN 或循環關鍵字前聲明。DECLARE 必須在 BEGIN 之後、其他語句之前。FOR 循環,僅有上述三種。autocommit=0 批次提交,減少日誌刷盤。掌握三大循環與流程控制,靈活編寫高效儲存過程。