• 关于MySql中使用IFNULL()函数失效的问题。


        今天在学习时,碰到一个问题:在联表查询取得结果后,如果取得的结果是空值,则给一个默认值,如果不是空值,则返回这个值。

    下面我们来看看业务场景:

           在menu表中:

    存储的是前端页面的菜单配置,注意成员权限管理,报表权限管理和配置工具,这三个菜单是项目管理这个菜单的子菜单,他们通过parent_id这个字段进行关联。

    在另外一张映射表project_menu中:

    在将菜单归属到具体的项目下时,依然要把配置的父子菜单进行关联,但是在这里关联的id和上面关联的id是不一样的。

    现在需求就是,在插入到project_menu表时,需要在插入时将子菜单的parent_id顺带插入其中。如果这个目录不是某个已存在目录的子菜单时,则parent_id默认是0,如果是某个菜单的子菜单,则需要关联表的查询,算出当前子目录的parent_id。

    我们来看看一开始错误的写法:

    1  SELECT IFNULL(id,0) from project_menu where code =
    2  (SELECT code FROM menu where id =
    3  (SELECT parent_id from menu where code = #{menuCode} and parent_id != 0)) 
    4   AND project_id = #{projectId}

    通过表的关联查询,得到当前目录的值,由于mybatis返回的值类型为int,所以如果查询到的值为null时,后台会报错,因此使用了IFNULL()函数,当id为null时,默认返回0。

    但是这样做,在调试的时候,mybatis却一直报错该语句尝试返回null但定义的返回类型时int。说明这个函数并没有起作用。那为什么没有起作用呢?

    那是因为这条语句的查询结果就是空的,也就是说,当传进来的参数是非子菜单时时,下面这条语句的返回值就是null

     1 (SELECT parent_id from menu where code = #{menuCode} and parent_id != 0) 

    当这条语句返回null时,整条语句的返回值都是空的(where分支比select分支优先执行),这时,等价于下面这条语句:

     1 SELECT IFNULL(id,0) from project_menu where code = NULL 

    这就不是这个当id为空时,用0替换id返回这个概念了,因为当语句本身就是null时,语句中的函数还会起作用吗?

    所以,此方法行不通,附上解决方案:

     1 SELECT 
     2     CASE
     3     WHEN (SELECT parent_id from menu where code = #{code}) = 0  
     4      THEN  0
     5      ELSE 
     6      (SELECT id from project_menu where code =
     7      (SELECT code FROM menu where id =
     8      (SELECT parent_id from menu where code =#{code} ))
     9      AND project_id=#{projectId})
    10      END

    使用条件判断选择语句。亲测有效。

  • 相关阅读:
    vSphere 6.5支持512e,NVMe SSD呢?
    分布式队列神器 Celery
    www.coursera.org
    各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解
    SSD S.M.A.R.T
    2018世界人工智能大会在上海开幕
    ER TO SQL语句
    E-R图样例
    关于微软的.NET版本系列
    ArcGIS 10.6 安装破解教程
  • 原文地址:https://www.cnblogs.com/jy107600/p/7161389.html
Copyright © 2020-2023  润新知