MySQL 模糊搜索
MySQL 模糊搜索: LIKE BINARY 是区分大小写的; LIKE 是否区分大小写,取决于表的 COLLATE,如果 COLLATE=utf8_bin 即二进制形式就是区分大小写的,否则是不区分的。
在 ORM 中过滤的时候会写 xxx.objects.filter(name__contains=‘sxn’) 和 xxx.objects.filter(name__icontains=‘sxn’) 转成的 SQL分别是: LIKE BINARY 和 LIKE
(drf_poc_env) root@robert-Ubuntu:/media/sf_WorkSpace/drf_poc# python manage.py shell Python 2.7.12 (default, Nov 12 2018, 14:36:49) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> >>> from app01.models import UserInfo >>> >>> UserInfo.objects.filter(username__contains='SXN') ----用的是 LIKE BINARY DEBUG 2020-04-01 11:01:07,836 4942 140546619713280 utils 90 Line (0.001) SELECT `app01_userinfo`.`id`, `app01_userinfo`.`user_type`, `app01_userinfo`.`username`, `app01_userinfo`.`password` FROM `app01_userinfo` WHERE `app01_userinfo`.`username` LIKE BINARY '%SXN%' LIMIT 21; args=(u'%SXN%',) <QuerySet []> >>> >>> >>> >>> UserInfo.objects.filter(username__icontains='SXN') ----用的是 LIKE DEBUG 2020-04-01 11:01:25,360 4942 140546619713280 utils 90 Line (0.001) SELECT `app01_userinfo`.`id`, `app01_userinfo`.`user_type`, `app01_userinfo`.`username`, `app01_userinfo`.`password` FROM `app01_userinfo` WHERE `app01_userinfo`.`username` LIKE '%SXN%' LIMIT 21; args=(u'%SXN%',) <QuerySet [<UserInfo: UserInfo object>]> >>> >>> mysql> show create table app01_userinfo \G -----注意表的 COLLATE 用是默认值,并不是COLLATE=utf8_bin *************************** 1. row *************************** Table: app01_userinfo Create Table: CREATE TABLE `app01_userinfo` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_type` int(11) NOT NULL, `username` varchar(32) NOT NULL, `password` varchar(32) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 1 row in set (0.01 sec) mysql> mysql> mysql> select * from app01_userinfo where username like binary '%sxn%'; +----+-----------+----------+----------+ | id | user_type | username | password | +----+-----------+----------+----------+ | 2 | 2 | sxn | 655 | +----+-----------+----------+----------+ 1 row in set (0.00 sec) mysql> mysql> select * from app01_userinfo where username like binary '%SXN%'; Empty set (0.00 sec) mysql> mysql> mysql> mysql> select * from app01_userinfo where username like '%sxn%'; +----+-----------+----------+----------+ | id | user_type | username | password | +----+-----------+----------+----------+ | 2 | 2 | sxn | 655 | +----+-----------+----------+----------+ 1 row in set (0.00 sec) mysql> mysql> select * from app01_userinfo where username like '%SXN%'; +----+-----------+----------+----------+ | id | user_type | username | password | +----+-----------+----------+----------+ | 2 | 2 | sxn | 655 | +----+-----------+----------+----------+ 1 row in set (0.00 sec) mysql>
mysql> show create table db_work_order \G --------- 注意表的 COLLATE=utf8_bin *************************** 1. row *************************** Table: db_work_order Create Table: CREATE TABLE `db_work_order` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `order_num` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '工单编号', `order_type` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '工单类型', ...... `create_time` datetime(6) NOT NULL COMMENT '创建时间', `update_time` datetime(6) NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uqi_ordernum` (`order_num`), KEY `created_time` (`create_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1578 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='数据库类别的工单表' 1 row in set (0.05 sec) mysql> mysql> ------可以看到是区分大小写的------ mysql> select id, order_num from db_work_order where order_num LIKE '%DB_change%' limit 3; Empty set (0.01 sec) mysql> mysql> select id, order_num from db_work_order where order_num LIKE '%db_change%' limit 3; +-----+-----------------------+ | id | order_num | +-----+-----------------------+ | 392 | db_change202003030106 | | 335 | db_change202003040029 | | 67 | db_change202003040078 | +-----+-----------------------+ 3 rows in set (0.00 sec) mysql> 是不是和环境变量也有关系?这个待确定 mysql> show variables like '%lower%'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | lower_case_file_system | ON | | lower_case_table_names | 1 | +------------------------+-------+ 2 rows in set, 1 warning (0.00 sec) mysql>
SQL WHERE 中的空格
mysql> show create table db_work_order \G --------- 注意表的 COLLATE=utf8_bin *************************** 1. row *************************** Table: db_work_order Create Table: CREATE TABLE `db_work_order` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `order_num` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '工单编号', `order_type` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '工单类型', ...... `create_time` datetime(6) NOT NULL COMMENT '创建时间', `update_time` datetime(6) NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uqi_ordernum` (`order_num`), KEY `created_time` (`create_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1578 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='数据库类别的工单表' mysql> mysql> select order_num, order_type, length(order_type) from db_work_order where order_type = 'cds_change_bak ' limit 3; +----------------------------+----------------+--------------------+ | order_num | order_type | length(order_type) | +----------------------------+----------------+--------------------+ | cds_change_bak202003050001 | cds_change_bak | 14 | | cds_change_bak202003050002 | cds_change_bak | 14 | | cds_change_bak202003060001 | cds_change_bak | 14 | +----------------------------+----------------+--------------------+ 3 rows in set (0.00 sec) mysql>
因为 order_type 的类型是 varchar 所以在 WHERE 中会忽略 'cds_change_bak ’ 中的空格,因为在varcahr 在存储的时候就会把后缀的空格给截断,注意前导空格不会忽略。