MySQL存儲過程 CASE語句
除了IF語句,MySQL提供了一個替代的條件語句CASE。 MySQL CASE語句使代碼更加可讀和高效。
CASE語句有兩種形式:簡單的搜索CASE語句。
簡單CASE語句
我們來看一下簡單CASE語句的語法:
CASE case_expression WHEN when_expression_1 THEN commands WHEN when_expression_2 THEN commands ... ELSE commands END CASE;
您可以使用簡單CASE語句來檢查表達式的值與一組唯一值的匹配。
case_expression可以是任何有效的表達式。我們將case_expression的值與每個WHEN子句中的when_expression進行比較,例如when_expression_1,when_expression_2等。如果case_expression和when_expression_n的值相等,則執行相應的WHEN分支中的命令(commands)。
如果WHEN子句中的when_expression與case_expression的值匹配,則ELSE子句中的命令將被執行。ELSE子句是可選的。 如果省略ELSE子句,並且找不到匹配項,MySQL將引發錯誤。
以下示例說明如何使用簡單的CASE語句:
DELIMITER $$ CREATE PROCEDURE GetCustomerShipping( in p_customerNumber int(11), out p_shiping varchar(50)) BEGIN DECLARE customerCountry varchar(50); SELECT country INTO customerCountry FROM customers WHERE customerNumber = p_customerNumber; CASE customerCountry WHEN 'USA' THEN SET p_shiping = '2-day Shipping'; WHEN 'Canada' THEN SET p_shiping = '3-day Shipping'; ELSE SET p_shiping = '5-day Shipping'; END CASE; END$$
上面存儲過程是如何工作的?
-
GetCustomerShipping存儲過程接受客戶編號作為IN參數,並根據客戶所在國家返回運送時間。 -
在存儲過程中,首先,我們根據輸入的客戶編號得到客戶的國家。然后使用簡單
CASE語句來比較客戶的國家來確定運送期。如果客戶位於美國(USA),則運送期為2天。 如果客戶在加拿大,運送期為3天。 來自其他國家的客戶則需要5天的運輸時間。
以下流程圖顯示了確定運輸時間的邏輯。

以下是上述存儲過程的測試腳本
SET @customerNo = 112; SELECT country into @country FROM customers WHERE customernumber = @customerNo; CALL GetCustomerShipping(@customerNo,@shipping); SELECT @customerNo AS Customer, @country AS Country, @shipping AS Shipping;
執行上面代碼,得到以下結果
+----------+---------+----------------+ | Customer | Country | Shipping | +----------+---------+----------------+ | 112 | USA | 2-day Shipping | +----------+---------+----------------+ 1 row in set
可搜索CASE語句
簡單CASE語句僅允許您將表達式的值與一組不同的值進行匹配。 為了執行更復雜的匹配,如范圍,您可以使用可搜索CASE語句。 可搜索CASE語句等同於IF語句,但是它的構造更加可讀。
以下說明可搜索CASE語句的語法:
CASE WHEN condition_1 THEN commands WHEN condition_2 THEN commands ... ELSE commands END CASE;
MySQL評估求值WHEN子句中的每個條件,直到找到一個值為TRUE的條件,然后執行THEN子句中的相應命令(commands)。
如果沒有一個條件為TRUE,則執行ELSE子句中的命令(commands)。如果不指定ELSE子句,並且沒有一個條件為TRUE,MySQL將發出錯誤消息。
MySQL不允許在THEN或ELSE子句中使用空的命令。 如果您不想處理ELSE子句中的邏輯,同時又要防止MySQL引發錯誤,則可以在ELSE子句中放置一個空的BEGIN END塊。
以下示例演示如何使用可搜索CASE語句來根據客戶的信用額度來查找客戶級:SILVER,GOLD或PLATINUM。
DELIMITER $$ CREATE PROCEDURE GetCustomerLevel( in p_customerNumber int(11), out p_customerLevel varchar(10)) BEGIN DECLARE creditlim double; SELECT creditlimit INTO creditlim FROM customers WHERE customerNumber = p_customerNumber; CASE WHEN creditlim > 50000 THEN SET p_customerLevel = 'PLATINUM'; WHEN (creditlim <= 50000 AND creditlim >= 10000) THEN SET p_customerLevel = 'GOLD'; WHEN creditlim < 10000 THEN SET p_customerLevel = 'SILVER'; END CASE; END$$
在上面查詢語句邏輯中,如果信用額度是:
- 大於
50K,則客戶是PLATINUM客戶。 - 小於
50K,大於10K,則客戶是GOLD客戶。 - 小於
10K,那么客戶就是SILVER客戶。
我們可以通過執行以下測試腳本來測試存儲過程:
CALL GetCustomerLevel(112,@level); SELECT @level AS 'Customer Level';
執行上面查詢語句,得到以下結果
+----------------+ | Customer Level | +----------------+ | PLATINUM | +----------------+ 1 row in set
在本教程中,介紹了如何使用兩種形式的MySQL CASE語句,包括簡單CASE語句和可搜索CASE語句。
現在將給您一些技巧,以便您在存儲過程中在什么情況分別選擇IF和CASE語句。
MySQL提供IF和CASE語句,使您能夠根據某些條件(稱為流控制)執行一個SQL代碼塊。那么您應該使用什么語句? 對於大多數開發人員,在IF和CASE之間進行選擇只是個人偏好的問題。但是,當您決定使用IF或CASE時,應該考慮以下幾點:
- 當將單個表達式與唯一值的范圍進行比較時,簡單CASE語句比IF語句更易讀。另外,簡單
CASE語句比IF語句更有效率。 - 當您根據多個值檢查復雜表達式時,
IF語句更容易理解。 - 如果您選擇使用
CASE語句,則必須確保至少有一個CASE條件匹配。否則,需要定義一個錯誤處理程序來捕獲錯誤。IF語句則不需要處理錯誤。 - 在大多數組織(公司)中,總是有一些所謂的開發指導文件,為開發人員提供了編程風格的命名約定和指導,那么您應參考本文檔並遵循開發實踐。
- 在某些情況下,
IF和CASE混合使用反而使您的存儲過程更加可讀和高效。
