首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 條件判斷與流程控制:IF、CASE、WHILE 在函數與儲存過程中的實戰用法

     編輯:MySQL 綜合教學

流程控制語句分類

類別語句使用範圍返回值
條件判斷IF ... THEN ... ELSEIF ... ELSE ... END IF儲存過程/函數/觸發器/事件無 (語句)
條件表達式IF(condition, true_val, false_val)**任何 SQL 位置** (SELECT、WHERE、SET)有 (表達式)
多分支CASE WHEN ... THEN ... ELSE ... END CASE儲存過程/函數/觸發器/事件無 (語句)
簡單 CASECASE expr WHEN val THEN ... END CASE同上無
迴圈WHILE / REPEAT / LOOP同上無

IF 函數 vs IF 語句

-- IF 函數 (表達式,可用於 SELECT)
SELECT IF(score >= 60, 'Pass', 'Fail') AS result FROM exams;

-- IF 語句 (流程控制,僅程式區塊)
CREATE FUNCTION grade(score INT) RETURNS VARCHAR(10)
BEGIN
    DECLARE result VARCHAR(10);
    IF score >= 85 THEN SET result = 'Excellent';
    ELSEIF score >= 60 THEN SET result = 'Pass';
    ELSE SET result = 'Fail';
    END IF;
    RETURN result;
END;

CASE 語句兩種形式

搜尋式 CASE (條件表達式)

CASE 
    WHEN score >= 90 THEN 'A'
    WHEN score >= 80 THEN 'B'
    WHEN score >= 70 THEN 'C'
    ELSE 'D'
END CASE;

簡單 CASE (值比較)

CASE day_of_week
    WHEN 1 THEN 'Mon'
    WHEN 2 THEN 'Tue'
    ...
    ELSE 'Invalid'
END CASE;

WHILE 迴圈實戰:計算最接近的 12 倍數

DELIMITER //

CREATE FUNCTION `round_to_dozen`(qty INT) RETURNS INT
DETERMINISTIC
BEGIN
    WHILE qty % 12 > 0 DO
        SET qty = qty + 1;
    END WHILE;
    RETURN qty;
END//

DELIMITER ;

SELECT round_to_dozen(10);  -- 12
SELECT round_to_dozen(24);  -- 24
SELECT round_to_dozen(25);  -- 36

帶條件判斷的 WHILE 迴圈

DELIMITER $$

CREATE PROCEDURE `print_odd_while`()
BEGIN
    DECLARE i INT DEFAULT 1;
    loop_label: WHILE i <= 10 DO
        IF (i % 2) <> 0 THEN
            SELECT CONCAT(i, ' is odd');
        END IF;
        SET i = i + 1;
    END WHILE loop_label;
END$$

DELIMITER ;

CALL print_odd_while();

進階模式:動態 SQL + 條件構建

CREATE PROCEDURE `dynamic_query`(IN tbl_name VARCHAR(64), IN filter_json JSON)
BEGIN
    DECLARE sql_text TEXT DEFAULT 'SELECT * FROM ';
    DECLARE where_clause TEXT DEFAULT '';
    
    SET sql_text = CONCAT(sql_text, '`', tbl_name, '`');
    
    IF JSON_CONTAINS_PATH(filter_json, 'one', '$.status') THEN
        SET where_clause = CONCAT(where_clause, ' AND `status` = ', JSON_UNQUOTE(JSON_EXTRACT(filter_json, '$.status')));
    END IF;
    
    IF JSON_CONTAINS_PATH(filter_json, 'one', '$.date_from') THEN
        SET where_clause = CONCAT(where_clause, ' AND `created_at` >= ', JSON_UNQUOTE(JSON_EXTRACT(filter_json, '$.date_from')));
    END IF;
    
    IF where_clause <> '' THEN
        SET sql_text = CONCAT(sql_text, ' WHERE ', SUBSTRING(where_clause, 5)); -- 移除前導 ' AND '
    END IF;
    
    SET @stmt = sql_text;
    PREPARE stmt FROM @stmt;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END;

效能與安全提醒

  • 動態 SQL 預防注入:所有外部輸入**必須**經 QUOTE() 或參數綁定 (PREPARE ... USING),嚴禁直接拼接。
  • 函數決定性:相同輸入必回傳相同結果,標記 DETERMINISTIC 允許查詢緩存/複製優化。
  • 避免在迴圈中執行單條 DML:批次化、集合操作、臨時表 + 單次 JOIN。
  • 最大遞歸深度:max_sp_recursion_depth (預設 0 禁用),啟用後小心棧溢位。

總結

MySQL 流程控制核心在於**區分「語句」與「表達式」**:**IF/CASE/WHILE/LOOP** 是語句,僅能在 `BEGIN ... END` 程式區塊使用;**IF()/CASE 表達式** 可內嵌於任何 SQL。掌握這一界限,才能在正確位置使用正確工具,寫出安全、高效、可維護的儲存邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved