MySQL CASE语句

时间:2019-11-20 08:52:29  来源:igfitidea点击:

简介:在本教程中,您将学习如何使用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语句。