zoukankan      html  css  js  c++  java
  • MySQL中的case when 中对于NULL值判断的坑

    sql中的case when 有点类似于Java中的switch语句,比较灵活,但是在Mysql中对于Null的处理有点特殊

    Mysql中case when语法:

    语法1:

    CASE case_value
        WHEN when_value THEN statement_list
        [WHEN when_value THEN statement_list] ...
        [ELSE statement_list]
    END CASE
    

      

    语法2:

    CASE
        WHEN search_condition THEN statement_list
        [WHEN search_condition THEN statement_list] ...
        [ELSE statement_list]
    END CASE
    

      

    注意:  这两种语法是有区别的,区别如下:

    1:第一种语法:case_value必须是一个表达式,例如 userid%2=1或者username is null等。该种语法不能用于测试NULL。

    2:第二种语法CASE后面不需要变量或者表达式,直接执行时候评估每一个WHEN后面的条件,如果满足则执行。

    案例实战:

    表结构如下:a 值为null, b值为1

    mysql> SELECT NULL AS a, 1 AS b;
    +------+---+
    | a    | b |
    +------+---+
    | NULL | 1 |
    +------+---+
    

      

    现在实现,如果a值为null 则取b值,否则取a值

    方法1: ifnull 用法

    SELECT
    	IFNULL(a, b) AS new,
    	a,
    	b
    FROM
    	-- 创建临时表: a 的值为null ,b为1
    	(SELECT NULL AS a, 1 AS b) tmp;
    

      

     方法2: case when 用法

    SELECT
    	(
    		CASE a
    		WHEN a IS NULL THEN
    			b
    		ELSE
    			a
    		END
    	) AS new,
    	a,
    	b
    FROM
    	(SELECT NULL AS a, 1 AS b) tmp;
    

      

    发现得到的结果不对,new 的值居然为null ,而不是我们想要的1.

    为什么会出现这个错误呢?是将第一种语法与第二种语法混用导致的,case 后面commission_pct 的值有两种:真实值或者为null,而 when 后面的commission_pct is null 也有两个值:true或者false,所以case 后面为null时候永远无法跟true或false匹配,因此输出不为null。

    对于该种情况如果必须要用语法1的话可以如下改写:

    SELECT
    	(
    		CASE a IS NULL
    		WHEN TRUE THEN b
    		ELSE a			
    		END
    	) AS new,
    	a,
    	b
    FROM
    	(SELECT NULL AS a, 1 AS b) tmp;
    

      

    也可以使用语法2写:

    SELECT
    	(
    		CASE 
    		WHEN a is NULL  THEN b	
    		ELSE a	
    		END
    	) AS new,
    	a,
    	b
    FROM
    	(SELECT NULL AS a, 1 AS b) tmp;
    

      

    注意另一种可能存在错误却不容易发现错误的情况:

    SELECT
    	(
    		CASE a 
    		WHEN NULL THEN b
    		ELSE a			
    		END
    	) AS new,
    	a,
    	b
    FROM
    	(SELECT NULL AS a, 1 AS b) tmp;
    

      

    看似没有问题,实际有问题,问题原因就是null的判断不能用=进行判断。简单说就是:语法1中的case表达式的值与后面的when的值使用的=进行判等,但是mysql中必须使用is 或者is not。

    总结:

    1:语法1是将case后面的表达式值计算好之后跟后面的when条件的值使用“=”进行判断相等,相等就进入该分支。

    2:语法2是不需要case后面有表达式,直接评估when后面的条件值即可,如果为true则进入。

  • 相关阅读:
    ASP.NET 表单验证 Part.1(理解表单验证)
    Silverlight 简介 Part.3(设计 Siverlight 页面)
    ASP.NET 成员资格 Part.3(LoginStatus、LoginView、PasswordRecovery)
    ASP.NET 网站部署 Part.1(安装IIS、复制文件部署网站)
    ASP.NET Dynamic Data Part.1(创建动态数据应用程序)
    ASP.NET 安全模型 Part.2(SSL)
    ASP.NET MVC Part.2(扩展基本的 MVC 应用程序)
    ASP.NET 网站部署 Part.2(使用 Web 部署)
    开发高级 Web 部件
    创建 Web 部件(WebPart 类、简单的 Web 部件)
  • 原文地址:https://www.cnblogs.com/echojson/p/11612650.html
Copyright © 2011-2022 走看看