MySQL CASE语句
简介:在本教程中,您将学习如何使用MySQL CASE语句在存储过程中构造复杂的条件语句。
除了IF语句外,MySQL还提供了一个称为CASE语句的替代条件语句,用于在存储过程中构造条件语句。
CASE语句使代码更具可读性和效率。
CASE语句有两种形式:simpleCASE和搜索的CASE语句。
请注意,如果要将if-else逻辑添加到SQL语句中,请使用与本教程中介绍的CASE语句不同的CASE表达式。
简单的CASE语句
以下是简单CASE语句的基本语法:
CASE case_value WHEN when_value1 THEN statements WHEN when_value2 THEN statements ... [ELSE else-statements] END CASE;
用这种语法,简单的CASE语句将case_value is与when_value1,when_value2,…进行顺序比较,直到发现一个相等。
当CASE找到等于when_value的case_value时,它将在相应的THEN子句中执行语句。
如果CASE找不到任何等于case_value的when_value,则如果ELSE子句可用,它将在ELSE子句中执行else语句。
当ELSE子句不存在并且CASE无法找到等于case_value的when_value时,将发出错误:
Case not found for CASE statement
请注意,case_value可以是文字值或表达式。
语句可以是一个或多个SQL语句,并且不能有零个语句。
为了避免case_value不等于when_value时的错误,可以在ELSE子句中使用空的BEGIN END块,如下所示:
CASE case_value WHEN when_value1 THEN ... WHEN when_value2 THEN ... ELSE BEGIN END; END CASE;
简单的CASE语句测试是否等于(=),您不能使用它来测试是否为NULL;因为NULL = NULL返回FALSE。
简单的CASE语句示例
以下存储过程说明了如何使用简单的CASE语句:
DELIMITER $$ CREATE PROCEDURE GetCustomerShipping( IN pCustomerNUmber INT, OUT pShipping VARCHAR(50) ) BEGIN DECLARE customerCountry VARCHAR(100); SELECT country INTO customerCountry FROM customers WHERE customerNumber = pCustomerNUmber; CASE customerCountry WHEN 'USA' THEN SET pShipping = '2-day Shipping'; WHEN 'Canada' THEN SET pShipping = '3-day Shipping'; ELSE SET pShipping = '5-day Shipping'; END CASE; END$$ DELIMITER ;
这个怎么运作。
GetCustomerShipping()存储过程接受两个参数:pCustomerNumber作为IN参数,而pShipping作为OUT参数。
在存储过程中:
首先,通过输入的客户编号从客户表中选择客户的国家/地区。
其次,使用简单的CASE语句根据客户所在的国家/地区确定运输时间。
如果客户位于美国,则运送时间为2天运送。
如果客户位于加拿大,则运送时间为3天运送。
来自其他国家的客户有5天的送货时间。
以下流程图演示了CASE语句确定运输时间的逻辑:
该语句调用存储过程并传递客户编号112:
CALL GetCustomerShipping(112,@shipping);
以下语句返回客户112的运输时间:
SELECT @shipping;
这是输出:
+----------------+ | @shipping | +----------------+ | 2-day Shipping | +----------------+ 1 row in set (0.00 sec)
搜索的CASE语句
简单的CASE语句仅允许您将一个值与一组不同的值进行比较。
要执行更复杂的匹配(例如范围),请使用搜索到的CASE语句。
搜索的CASE语句等效于IF语句,但是它比IF语句更具可读性。
这是搜索到的CASE语句的基本语法:
CASE WHEN search_condition1 THEN statements WHEN search_condition1 THEN statements ... [ELSE else-statements] END CASE;
使用这种语法,被搜索的CASE会对WHEN子句中的每个search_condition求值,直到找到一个条件值为TRUE的条件,然后执行相应的THEN子句语句。
如果没有search_condition评估为TRUE,则如果有ELSE子句可用,则CASE将在ELSE子句中执行else语句。
与简单的CASE语句类似,如果您不指定ELSE子句且没有条件为TRUE,则MySQL会产生相同的错误:
Case not found for CASE statement
MySQL还不允许您在THEN或ELSE子句中使用空语句。
如果您不想处理ELSE子句中的逻辑,同时又防止MySQL在没有search_condition为true的情况下引发错误,则可以在ELSE子句中使用空的BEGIN END块。
搜索的CASE语句示例
以下示例演示了如何使用搜索到的CASE语句根据客户的信用额度查找客户级别SILVER,GOLD或PLATINUM。
DELIMITER $$ CREATE PROCEDURE GetDeliveryStatus( IN pOrderNumber INT, OUT pDeliveryStatus VARCHAR(100) ) BEGIN DECLARE waitingDay INT DEFAULT 0; SELECT DATEDIFF(requiredDate, shippedDate) INTO waitingDay FROM orders WHERE orderNumber = pOrderNumber; CASE WHEN waitingDay = 0 THEN SET pDeliveryStatus = 'On Time'; WHEN waitingDay >= 1 AND waitingDay < 5 THEN SET pDeliveryStatus = 'Late'; WHEN waitingDay >= 5 THEN SET pDeliveryStatus = 'Very Late'; ELSE SET pDeliveryStatus = 'No Information'; END CASE; END$$ DELIMITER ;
这个怎么运作。
存储过程GetDeliveryStatus()接受订单号作为IN参数,并返回交货状态作为OUT参数。
首先,计算所需日期和发货日期之间的天数。
其次,使用搜索到的CASE语句根据等待天数确定交货状态:
如果等待天数为零,则表示交货准时。
当等待天数在1到5之间时,交货延迟。
如果等待天数超过5天,则交货时间很晚。
如果等待天数为NULL,否则,交货状态为ELSE子句中未指定任何信息。
该语句使用存储过程GetDeliveryStatus()获取订单10100的交付状态:
CALL GetDeliveryStatus(10100,@delivery);
结果如下:
MySQL CASE与IF
IF和CASE语句均允许您根据特定条件执行代码块。
在IF或CASE之间进行选择有时只是个人喜好问题。
以下是一些准则:
当您将单个表达式与一系列唯一值进行比较时,简单的CASE语句比IF语句更具可读性和效率。
当您基于多个值检查复杂的表达式时,IF语句更容易理解。
如果使用CASE语句,则必须确保至少满足一个CASE条件。
否则,您需要定义一个错误处理程序以捕获错误。
请注意,您不必使用IF语句执行此操作。在某些情况下,可以同时使用IF和CASE来使代码更具可读性和效率。
在本教程中,您学习了如何使用两种形式的MySQL CASE语句,包括简单的CASE语句和搜索的CASE语句。