今天在學習時,碰到一個問題:在聯表查詢取得結果后,如果取得的結果是空值,則給一個默認值,如果不是空值,則返回這個值。
下面我們來看看業務場景:
在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
使用條件判斷選擇語句。親測有效。
