关于mysql版本差异导致FIND_IN_SET()查询不到数据的问题
关于FIND_IN_SET()函数出现查询不到数据的情况
这次发现的问题,是在接手项目的时候,和安卓端小伙伴测试时候发现的,插入数据之后却查不出来,通过排查定位到FIND_IN_SET()函数,也是第一次接触FIND_IN_SET(),特此记录一下~
关于FIND_IN_SET():
官方涵义(MySQL手册中语法说明)
FIND_IN_SET(str,strlist) : str 要查询的字符串,strlist 需查询的字段,参数以”,”分隔,形式如 (1,2,6,8,10,22);该函数的作用是查询字段(strlist)中是否包含(str)的结果,返回结果为null或记录。
假如字符串str在由N个子链组成的字符串列表strlist 中,则返回值的范围在 1 到 N 之间。 一个字符串列表就是一个由一些被 ‘,’ 符号分开的子链组成的字符串。如果第一个参数是一个常数字符串,而第二个是type SET列,则FIND_IN_SET() 函数被优化,使用比特计算。 如果str不在strlist 或strlist 为空字符串,则返回值为 0 。如任意一个参数为NULL,则返回值为 NULL。这个函数在第一个参数包含一个逗号( , )时将无法正常运行。数为NULL,则返回值为 NULL。这个函数在第一个参数包含一个逗号( , )时将无法正常运行。
示例:
SELECT FIND_IN_SET('b', 'a,b,c,d');
// 结果:2
// 因为 b 在strlist集合中2的位置, a是位置1
select FIND_IN_SET('1', '1');
// 结果:1
// 这时候的strlist集合有点特殊,只有一个字符串
select FIND_IN_SET('2', '1,2');
// 结果:2
select FIND_IN_SET('6', '1');
// 结果:0 strlist中不存在str,所以返回0。
综上: FIND_IN_SET函数中,若前一个字符串包含在后一个字符串集合中,返回大于0的数,该数为前一个字符串在后一个字符串中的位置。
问题发生:
有一张发布作业表,表中有个varcher类型字段用于存储班级id,存入的形式是 ‘01,02,03’,而现在要用另外一张表,通过学生所在的班级id,从发布作业表中获取相关老师布置的作业,,接手项目时,sql语句如下:
SELECT
m.class_id,
m.prod_key,
m.dev_name,
w.id work_id,
w.title,
w.content,
w.is_open,
w.score,
w.file_url_list,
w.end_time,
w.create_author,
w.update_author
FROM
sc_work w,
sc_class_mem m
WHERE
w.id = 56
AND find_in_set(m.class_id, w.class_ids)
AND m.identity=0;
问题解决:
在安卓小伙伴进行测试的时候所拿到的相关字段数据是空的,通过debug发现执行这个sql语句后,获取到的值是null。但是本地数据与测试服务器的数据库数据是一致的,所以应该可以查询到值才对,所以我认为是前者写的sql语句有问题(因为此前就有出现过好几次这个问题,再加上我在本地执行sql语句查询不到任何数据),但我还是将映射文件中的sql语句放到测试服务器的数据库执行发现是可以查询到的,首先想到的是不是本地mysql版本(8.0.26)不支持这个函数,但是实际发现是支持的,然后又去看了一下库中表的字符集,发现是utf32,而我创建的时候是utf8mb4,然后便重新创建库,字符集选了utf32,测试是不是这个原因,但是实际结果发现并不是这个原因,于是便去查询相关资料,以及修改sql语句,我发现:
find_in_set(m.class_id, '45,46,46')
如果将两个字段任一换成’xx,xx,xx’,就可以查询的到,就很奇怪。
而网上资料全是讲解如何使用,千篇一律,没有起到帮助,想了很久,虽然一开始有想到了是不是数据库版本的问题,但是没有马上去测试这个想法,因为我觉得8.0.19和本地8.0.26应该差别不大才对啊,而且官方文档这个函数还存在,版本越高不是越能向下兼容? 查了一天,想了很久不知道问题出在哪里,最后还是在虚拟机拉取了一个mysql8.0.19的镜像下来,进行测试,最终发现是数据库版本的问题,至此问题得到解决,又长见识了~
漂亮!又浪费了一天时间~
更多推荐
所有评论(0)