萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 預存程序循環與條件判斷完整實戰指南

MySQL 5.0+ 引入預存程序,才支援在 SQL 內使用流程控制(IF、WHILE、LOOP、REPEAT、ITERATE、LEAVE)。本文詳細解析三種標準循環結構、條件判斷、參數傳遞與實戰範例,助你掌握伺服器端程式邏輯開發。

一、流程控制關鍵字速查

關鍵字用途適用場景
IF ... THEN ... ELSE ... END IF條件分支單一條件多重分支
CASE ... WHEN ... THEN ... END CASE多條件分支多值比對
WHILE condition DO ... END WHILE前測試循環已知循環次數或條件
REPEAT ... UNTIL condition END REPEAT後測試循環至少執行一次
LOOP ... END LOOP無條件循環配合 LEAVE/ITERATE 控制
LEAVE label跳出指定標籤循環等同 break
ITERATE label跳過本次迭代進入下一次等同 continue

二、三大標準循環結構實戰

1. WHILE 循環(前測試)

DELIMITER //
CREATE PROCEDURE test_while(IN in_count INT)
BEGIN
  DECLARE cnt INT DEFAULT 0;
  WHILE cnt < in_count DO
    SET cnt = cnt + 1;
  END WHILE;
  SELECT cnt AS result;
END//
DELIMITER ;

CALL test_while(10);  -- 輸出 10

特點: 先判斷條件再執行,若初始條件不滿足則零次執行。

2. REPEAT 循環(後測試)

DELIMITER //
CREATE PROCEDURE test_repeat(IN in_count INT)
BEGIN
  DECLARE cnt INT DEFAULT 0;
  REPEAT
    SET cnt = cnt + 1;
  UNTIL cnt >= in_count
  END REPEAT;
  SELECT cnt;
END//
DELIMITER ;

特點: 保證至少執行一次,適合「先做後判斷」邏輯。

3. LOOP 循環(配合標籤控制)

DELIMITER $$
CREATE PROCEDURE myProc()
BEGIN
  DECLARE i INT DEFAULT 0;
  loop1: LOOP
    SET i = i + 1;
    IF i >= 10 THEN
      LEAVE loop1;           -- 跳出循環
    ELSEIF MOD(i, 2) = 0 THEN
      ITERATE loop1;         -- 跳過偶數,直接下一輪
    END IF;
    SELECT CONCAT(i, ' is an odd number');
  END LOOP loop1;
END$$
DELIMITER ;

CALL myProc();  -- 輸出 1,3,5,7,9

特點: 最靈活,需自行控制終止條件,適合複雜跳轉邏輯。

三、帶參數與條件判斷的綜合範例

DELIMITER //
CREATE PROCEDURE increment(IN in_count INT)
BEGIN
  DECLARE cnt INT DEFAULT 0;
  increment_loop: LOOP
    SET cnt = cnt + 1;
    IF cnt < 20 THEN
      ITERATE increment_loop;   -- 計數器 < 20 時跳過後續,直接下一輪
    END IF;
    IF cnt > in_count THEN
      LEAVE increment_loop;     -- 超過傳入參數則結束
    END IF;
  END LOOP increment_loop;
  SELECT cnt AS final_count;
END//
DELIMITER ;

CALL increment(3);  -- 輸出 20(先跑到 20,再檢查 > 3 才結束)

邏輯解析:

  1. 計數器從 1 遞增到 20 時,ITERATE 導致直接進入下一輪,不執行後續判斷。
  2. 達到 20 後,cnt < 20 為假,進入第二個 IF,若 cnt > in_count 則 LEAVE。
  3. 呼叫 increment(3) 時,20 > 3 滿足,結束並返回 20。

四、函數中的流程控制(RETURN 替代 SELECT)

DELIMITER //
CREATE FUNCTION myFunction(quantity INT) RETURNS INT
DETERMINISTIC
BEGIN
  WHILE quantity MOD 12 > 0 DO
    SET quantity = quantity + 1;
  END WHILE;
  RETURN quantity;  -- 函數必須用 RETURN
END//
DELIMITER ;

SELECT myFunction(10);  -- 12(補齊到 12 的倍數)
SELECT myFunction(24);  -- 24

差異提醒: 函數用 RETURN 回傳單一值;預存程序用 SELECT 輸出結果集或 OUT 參數回傳。

五、最佳實踐與避坑指南

  1. 必須修改 DELIMITER: 定義程序/函數時將語句結束符改為 // 或 $$,結束後改回 ;。
  2. 避免無限循環: 確保循環內有明確的 LEAVE 條件,並在開發環境測試小數據驗證。
  3. 變數宣告在開頭: DECLARE 必須置於 BEGIN 之後、任何其他語句之前。
  4. 標籤命名規範: 使用有語意名稱(如 process_loop),避免巢狀循環混淆。
  5. 效能考量: 複雜運算盡量在應用層處理,預存程序適合封裝資料庫邏輯、減少網路往返。

六、總結

MySQL 預存程序提供完整的程序化能力:WHILE 適合已知次數、REPEAT 適合至少一次、LOOP 適合複雜控制流。配合 IF/CASE、LEAVE/ITERATE、標籤機制,可實現各類業務邏輯。實務上建議「能在應用層解決的不下放到資料庫」,僅將高頻、原子性強的資料操作封裝為預存程序。

copyright © 萬盛學電腦網 all rights reserved