如何理解这条Mysql模糊查询语句?

如何理解这条Mysql模糊查询语句

select * from `user` where username like "%" 'name' "%"(可以查出数据)
select * from `user` where username like "%" "name" "%"(查不出来数据)

我不太理解这两种写法字符串的拼接结果是什么

阅读 1.4k
4 个回答

楼上说的只有在各个字符串之间使用空格作分隔时,这几个字符串才会连接起来(相当于like '%name%'),题目里的示例第一个查得出来数据而第二个查不出来,我试了下是没有用空格作分隔的情况。(如果用了空格则和楼上的回答一样两个都可以查得出来,见我截的官方文档里的示例),猜测是解析的时候用了某种转义再拼接?
image.png
话说回来官方的用法里并没有也不推荐用题目里的写法,如果要研究MYSQL是怎么处理这样的情况的话可以了解,正式使用的时候还是老老实实使用官方的示例和推荐的用法吧,比如CONCAT函数、CONCAT_WS函数以及这种字符串之间使用空格并排的用法。

连着写的引号括起的字符串会合成一个,
以上两种写法都能返回数据:

select username,2 from user where username like "%" "test" "%";

返回:

username2
test1232

使用单引号 ' 和双引号 " 的区别如下:

  1. 单引号 ':

    • 单引号用于包裹字符串文字或文本值。
    • 在单引号中,特殊字符如 ' 需要使用转义字符 '' 来表示。
    • 单引号查询会进行模糊匹配,包括空格等特殊字符。
  2. 双引号 ":

    • 双引号用于标识数据库对象,如表名、列名等。
    • 双引号查询会精确匹配,不会包括空格等特殊字符。

在这两个查询中:

  1. select * from user where username like "%" 'name' "%":

    • 这个查询使用单引号 ' 包裹 name
    • 它会进行模糊匹配,查找 username 包含 "name" 的记录。
  2. select * from user where username like "%" "name" "%":

    • 这个查询使用双引号 " 包裹 name
    • 它会进行精确匹配,查找 username 中包含字符串 "name" 的记录。

第一个查询可以查出数据,而第二个查询查不出数据
因为用户名中可能没有严格包含 "name" 的情况。

语法层面的,已经有回答解释过了,这是补充一下查询部分的。

你既然没有说 MySQL 版本,那我就只好用较新版本的 MySQL 来测,使用 explain 后再执行 show warnings; 可以看到 MySQL 处理后的语句,可以看到这两个的查询最终的 SQL 筛选部分都是一样的,而我这里执行也符合预期,两个查询都查到了数据,而不是你原题中说的那样。

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.30    |
+-----------+
1 row in set (0.00 sec)

mysql> explain select name from fake_person where name like "%" "米" "%";
+----+-------------+-------------+------------+-------+---------------+----------+---------+------+---------+----------+--------------------------+
| id | select_type | table       | partitions | type  | possible_keys | key      | key_len | ref  | rows    | filtered | Extra                    |
+----+-------------+-------------+------------+-------+---------------+----------+---------+------+---------+----------+--------------------------+
|  1 | SIMPLE      | fake_person | NULL       | index | NULL          | idx_name | 51      | NULL | 1955381 |    11.11 | Using where; Using index |
+----+-------------+-------------+------------+-------+---------------+----------+---------+------+---------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message
                                            |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `big_data`.`fake_person`.`name` AS `name` from `big_data`.`fake_person` where (`big_data`.`fake_person`.`name` like '%米%')  |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> explain select name from fake_person where name like "%" '米' "%";
+----+-------------+-------------+------------+-------+---------------+----------+---------+------+---------+----------+--------------------------+
| id | select_type | table       | partitions | type  | possible_keys | key      | key_len | ref  | rows    | filtered | Extra                    |
+----+-------------+-------------+------------+-------+---------------+----------+---------+------+---------+----------+--------------------------+
|  1 | SIMPLE      | fake_person | NULL       | index | NULL          | idx_name | 51      | NULL | 1955381 |    11.11 | Using where; Using index |
+----+-------------+-------------+------------+-------+---------------+----------+---------+------+---------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message
                                            |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `big_data`.`fake_person`.`name` AS `name` from `big_data`.`fake_person` where (`big_data`.`fake_person`.`name` like '%米%')  |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

或者在 MySQL 8 以上使用 explain analyze 也可以看到筛选部分都是一致的。

mysql> explain analyze select name from fake_person where name like "%" '米' "%";
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                                                                |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Filter: (fake_person.`name` like '%米%')  (cost=234625.68 rows=217243) (actual time=275.600..517.165 rows=6606 loops=1)
    -> Covering index scan on fake_person using idx_name  (cost=234625.68 rows=1955381) (actual time=0.058..328.245 rows=2000000 loops=1)
  |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.52 sec)

mysql> explain analyze select name from fake_person where name like "%" "米" "%";
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                                                                |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Filter: (fake_person.`name` like '%米%')  (cost=234625.68 rows=217243) (actual time=342.288..558.971 rows=6606 loops=1)
    -> Covering index scan on fake_person using idx_name  (cost=234625.68 rows=1955381) (actual time=0.025..346.099 rows=2000000 loops=1)
  |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.56 sec)

最后亦或者使用 Optimizer Trace 这两条 SQL 得到的筛选也是一样的。

image.png
image.png

推荐问题