# MySQL的循環語句有哪些
MySQL作為最流行的關系型數據庫之一,提供了多種流程控制語句來實現復雜的業務邏輯處理。本文將詳細介紹MySQL中的三種主要循環語句:`WHILE`、`REPEAT`和`LOOP`,并通過實際示例演示它們的用法。
## 一、循環語句概述
在存儲過程、函數和觸發器中,MySQL提供了以下三種循環結構:
1. **WHILE循環** - 先判斷條件后執行
2. **REPEAT循環** - 先執行后判斷條件
3. **LOOP循環** - 無限循環配合LEAVE退出
這些循環結構通常與以下控制語句配合使用:
- `LEAVE`:相當于其他語言的break
- `ITERATE`:相當于其他語言的continue
## 二、WHILE循環
### 基本語法
```sql
[標簽:] WHILE 條件 DO
循環體;
END WHILE [標簽];
DELIMITER //
CREATE PROCEDURE while_demo1()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 5 DO
SELECT CONCAT('當前值: ', i);
SET i = i + 1;
END WHILE;
END //
DELIMITER ;
CALL while_demo1();
DELIMITER //
CREATE PROCEDURE while_demo2(IN max_num INT)
BEGIN
DECLARE i INT DEFAULT 0;
outer_label: WHILE i < max_num DO
SET i = i + 1;
IF i = 3 THEN ITERATE outer_label; -- 跳過3
ELSEIF i > 7 THEN LEAVE outer_label; -- 大于7時退出
END IF;
SELECT i;
END WHILE;
END //
DELIMITER ;
CALL while_demo2(10);
[標簽:] REPEAT
循環體;
UNTIL 條件 END REPEAT [標簽];
DELIMITER //
CREATE PROCEDURE repeat_demo1()
BEGIN
DECLARE count INT DEFAULT 5;
REPEAT
SELECT CONCAT('倒計時: ', count);
SET count = count - 1;
UNTIL count = 0 END REPEAT;
END //
DELIMITER ;
CALL repeat_demo1();
DELIMITER //
CREATE PROCEDURE process_users()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE user_id INT;
DECLARE cur CURSOR FOR SELECT id FROM users;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
REPEAT
FETCH cur INTO user_id;
IF NOT done THEN
-- 處理每個用戶
UPDATE user_stats SET processed = 1 WHERE uid = user_id;
END IF;
UNTIL done END REPEAT;
CLOSE cur;
END //
DELIMITER ;
[標簽:] LOOP
循環體;
IF 條件 THEN LEAVE [標簽]; END IF;
END LOOP [標簽];
DELIMITER //
CREATE PROCEDURE fibonacci(IN n INT)
BEGIN
DECLARE a INT DEFAULT 0;
DECLARE b INT DEFAULT 1;
DECLARE i INT DEFAULT 1;
DECLARE temp INT;
fib_loop: LOOP
IF i > n THEN LEAVE fib_loop; END IF;
SELECT CONCAT('第', i, '項: ', a);
SET temp = a + b;
SET a = b;
SET b = temp;
SET i = i + 1;
END LOOP;
END //
DELIMITER ;
CALL fibonacci(10);
DELIMITER //
CREATE PROCEDURE insert_test_data(IN rows_num INT)
BEGIN
DECLARE i INT DEFAULT 1;
insert_loop: LOOP
IF i > rows_num THEN LEAVE insert_loop; END IF;
INSERT INTO test_table(name, create_time)
VALUES(CONCAT('user', i), NOW());
SET i = i + 1;
END LOOP;
END //
DELIMITER ;
| 特性 | WHILE | REPEAT | LOOP |
|---|---|---|---|
| 條件檢查時機 | 循環前檢查 | 循環后檢查 | 無內置檢查 |
| 最少執行次數 | 0次 | 1次 | 無限次 |
| 退出方式 | 條件為false | 條件為true | 必須使用LEAVE |
| 適用場景 | 不確定循環次數 | 至少執行一次 | 復雜退出邏輯 |
性能考慮:
死循環預防:
變量作用域:
標簽使用:
DELIMITER //
CREATE PROCEDURE migrate_old_data()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE old_id INT;
DECLARE cur CURSOR FOR SELECT id FROM old_table;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
migration_loop: LOOP
FETCH cur INTO old_id;
IF done THEN LEAVE migration_loop; END IF;
-- 復雜的數據轉換邏輯
INSERT INTO new_table(id, name)
SELECT id, CONCAT('new_', username) FROM old_table WHERE id = old_id;
-- 記錄遷移日志
INSERT INTO migration_log(old_id, migrate_time) VALUES(old_id, NOW());
END LOOP;
CLOSE cur;
END //
DELIMITER ;
DELIMITER //
CREATE PROCEDURE fix_invalid_records()
BEGIN
DECLARE total_fixed INT DEFAULT 0;
DECLARE batch_size INT DEFAULT 100;
DECLARE affected INT;
WHILE EXISTS (SELECT 1 FROM orders WHERE status = 'invalid' LIMIT 1) DO
UPDATE orders
SET status = 'processed'
WHERE status = 'invalid'
LIMIT batch_size;
SET affected = ROW_COUNT();
SET total_fixed = total_fixed + affected;
-- 避免鎖表時間過長
DO SLEEP(0.5);
END WHILE;
SELECT CONCAT('已修復', total_fixed, '條記錄');
END //
DELIMITER ;
MySQL提供了三種各具特色的循環結構,開發者可以根據具體需求選擇:
- 需要先檢查條件時使用WHILE
- 需要至少執行一次時使用REPEAT
- 需要完全控制循環邏輯時使用LOOP
合理使用循環語句可以大大增強存儲過程的處理能力,但同時要注意避免性能問題和無限循環。建議在復雜業務邏輯處理、數據遷移轉換等場景下結合事務使用循環結構。 “`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。