在使用Mybatis进行mysql数据查询的时候 , 因为给前端返回的数据要使用 CONCAT 函数拼接起来, 从而出现了一个bug 
然后主要的sql是
select t.id,
CONCAT(
(SELECT COUNT(1) FROM t_aqjcjl_jcjg g WHERE g.task_id = t.id AND g.jcjl = '3'),
'/',
(SELECT COUNT(1) FROM t_aqjcjl_jcjg g WHERE g.task_id = t.id AND g.jcjl = '2'),
'/',
(SELECT COUNT(1) FROM t_aqjcjl_jcjg g WHERE g.task_id = t.id AND g.jcjl = '1')
) AS wjyczc
from t_aqjcjl_task t
在DBeaver中执行之后发现数据的类型变成了VarBinary的类型 , 经过查阅得知是二进制类型,导致的二进制转换的base64的乱码。
可能的原因
子查询结果为 NULL
在 concat 函数里,要是任何一个子查询的结果为 NULL,那么 concat 函数的整个结果就会是 NULL。例如,当 t_aqjcjl_jcjg 表中不存在满足 g.task_id = t.id 且 g.jcjl = ‘3’ 条件的记录时,(select count(1) from t_aqjcjl_jcjg g where g.task_id = t.id and g.jcjl = ‘3’ ) 的结果就是 0,这本身没问题,但如果查询过程中因为某些原因返回 NULL,就会导致 concat 函数结果为 NULL。
不过在明确知道结果不为null的情况下查询结果也是相同
解决办法
使用 IFNULL 处理 NULL 值
加上ifnull之后这一列的值变成了正常的的字符串
原理探究
经过查阅资料和验证 , 在 SQL 查询中,当子查询可能返回 NULL 时,数据库引擎会隐式处理类型推断,而 IFNULL(或 COALESCE)函数会强制指定一个明确的类型。
确切的原因
-
子查询返回 NULL 时的类型不确定性
- 当子查询 (SELECT COUNT(1) FROM …) 没有匹配的行时,结果会返回 NULL(而不是 0)。
- 如果直接使用子查询结果(不加 IFNULL),某些数据库(如 MySQL)会将字段类型推断为 BINARY 或 VARBINARY,因为 NULL 的类型可能无法明确推断为数值类型。
-
CONCAT 函数对类型的隐式转换
- CONCAT 会将所有参数隐式转换为字符串,但如果子查询结果可能为 NULL,某些数据库会因类型不确定性将其视为二进制类型,而非字符串。
-
MyBatis 对二进制类型的处理
- 如果数据库返回 BINARY 类型,MyBatis 可能将其误判为二进制数据(如 BLOB),进而进行 Base64 编码,导致最终值显示为乱码(如 OS8wLzA=)。