關於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

 

使用條件判斷選擇語句。親測有效。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM