Find_in_set
官方原文
MySQL官方的描述:
- FIND_IN_SET(str,strlist)
假如字符串str 在由N 子链组成的字符串列表strlist 中, 则返回值的范围在 1 到 N 之间 。一个字符串列表就是一个由一些被‘,’符号分开的自链组成的字符串。如果第一个参数是一个常数字符串,而第二个是type SET列,则 FIND_IN_SET() 函数被优化,使用比特计算。如果str不在strlist 或strlist 为空字符串,则返回值为 0 。如任意一个参数为NULL,则返回值为 NULL。
mysql> SELECT FIND_IN_SET(‘b’,‘a,b,c,d’);//输出为2。就是找某个字符在字符串链的第几个。
mysql> SELECT FIND_IN_SET(‘h’,‘h,a,f,h,d’);//输出为1。只找最前面匹配的一个元素的位置。
mysql> SELECT FIND_IN_SET(‘重庆’,‘重庆,北京’);//输出为1,中文当然也行。
mysql> SELECT FIND_IN_SET(‘b’,‘’);//输出为0。没有就是0。
mysql> SELECT FIND_IN_SET(‘’,‘a,b,c,d’);//输出为0。没有就是0。
mysql> SELECT FIND_IN_SET(‘’,‘a,b,d’);//输出为3。这种两个逗号的就是空的。
mysql> SELECT FIND_IN_SET(‘’,‘,h,d’);//输出为1。这种也行。
mysql> SELECT FIND_IN_SET(‘ab’,‘a,b,c,d’);//输出为0。因为没有找到。
mysql> SELECT FIND_IN_SET(‘b’,null);//输出为null。有一个null输出就是null。
mysql> SELECT FIND_IN_SET(null,‘a,b,c,d’);//输出为null.。有一个null输出就是null。
mysql> SELECT FIND_IN_SET(‘c’,‘null,b,c,d’);//输出为3。这种不是null,这个null是被当作字符串的。
mysql> SELECT FIND_IN_SET(‘f,h’,‘h,a,f,h,d’);//输出为0,这种第一个参数有逗号的无法匹配,输出为0
链接地址:https://www.mysqlzh.com/doc/116.html
find_in_set()与in()的应用场景区别
select * from per where find_in_set(id,'2,3,4,5,6');
和
select * from per where id in(2,3,4,5,6);
结果是一样的。
区别
对于find_in_set()而言:
第二个参数无论是字符串还是数字都必须用单引号括起来, 并且字符串列表是用逗号隔开,是一个字符串列表整体。
对于in而言:
如果是检测的字段如果是数字类型的话就不能用单引号,因为这样会让结果出现偏差。
例子:
错误的写法:
select * from sys_role where role_id in('2,3,4,5,6');
看到只有一个结果,为什么呢?
因为隐式转换,但是一般情况下,in都是要完全匹配后面的某一个元素才能返回true的。
正确的写法:
select * from sys_role where role_id in(2,3,4,5,6);
一般情况下是要完全一样的in才能匹配到。上面的隐式转换是特殊情况,隐式转换的发生条件是你比较的数据和另一个数据不是一个数据类型时,会发生隐式转换,上面id是int类型的,但是in后面的’2,3,4,5,6’是字符串类型,所以进行了隐式转换,这里的隐式转换是把字符串转为了2,但是这里的隐式转换规则我不是很懂了,所以,最好我们让比较的类型一致,避免他的隐式转换。
in一般情况下就匹配完全相等的元素。而find_in_set是匹配第二个参数的字符串中的某一个子字符串。
创建一个测试的表:
CREATE TABLE `test1` (
`id` int(8) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`list` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `test1`(name,list) VALUES ('张三', '篮球,足球,羽毛球');
INSERT INTO `test1`(name,list) VALUES ('李四', '射箭,跳远,足球');
INSERT INTO `test1`(name,list) VALUES ('王武', '跳远,篮球');
INSERT INTO `test1`(name,list) VALUES ('小王', '射箭');
创建后的数据如下:
不发生隐私转换的情况下,下面这个sql执行不会找到数据:
SELECT id,name,list from test1 WHERE '篮球' IN(list);
除非,in括号内的数据和我们要比较的数据完全一样,才能匹配到,比如:
SELECT id,name,list from test1 WHERE '射箭' IN(list);
但是FIND_IN_SET可以匹配某个字段中包含某个子串的所有记录,就是只要括号里面元素有存在一样的就是ture,各元素之间用逗号隔开,并且外面加单引号。
小提示: find_in_set() 一般都写在 where关键字的后面!
如果要检验一个数据,是否是一个字符串的子字符串
下面两中做法都行。
find_in_set的做法是:
select * from sys_role where find_in_set(role_name,'普通员工,管理员,人事');
in的做法是:
select * from sys_role where role_name in('普通员工','管理员','人事');
自己的话
总之,in是每一个元素用逗号隔开的匹配。Find_in_set是括号里面是一个字符串,字符串内的每一个元素用逗号分开,虽然find_in_set的括号内用引号包裹起来,但是没有要求每一个元素一定要是字符串,你是int的也行呀。