MYSQL order by 排序的一个小问题探究

Posted Reborn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MYSQL order by 排序的一个小问题探究相关的知识,希望对你有一定的参考价值。

小问题发现:

select * from `sql` where id=1 order by (select 1 union select 2)     正常返回结果

mysql> select * from `sql` where id=1 order by (select 1 union select 2);
+----+------+
| id | new  |
+----+------+
|  1 | test |
+----+------+
1 row in set

mysql> select * from mysql.user where user=\'root\' order by (select 1 union select 2);  报错
1242 - Subquery returns more than 1 row

我的理解应该是都会报 Subquery returns more than 1 row 但是从mysql的运行结果来看不是这样的

继续看查询多条结果的情况

mysql> select * from `sql` where id=1 order by (select 1 union select 2);
+----+------+
| id | new  |
+----+------+
|  1 | test |
+----+------+
1 row in set

mysql> select * from `sql` order by (select 1 union select 2);
1242 - Subquery returns more than 1 row
mysql> select * from `sql` where id in(1,2) order by (select 1 union select 2);
1242 - Subquery returns more than 1 row
mysql> select * from `sql` where id in(1,2);
+----+--------------------+
| id | new                |
+----+--------------------+
|  1 | test               |
|  2 | sqlinjection test2 |
+----+--------------------+
2 rows in set

一条结果的时候不报错,多条结果报错。

经过DBA大牛的指点,DBA这样说的:

只要不走全表扫描,通过主键或者唯一索引能够定位到数据,就可以忽略后面的错误排序语法
如果走全表扫描或者查询的数据不止一条,就有排序语法错误

然后让执行  

mysql> explain select * from `sql` where id=1;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | sql   | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1 row in set
mysql> explain select * from `sql` where id=1;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | sql   | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1 row in set

mysql> explain select * from `sql` where id in (1,2);
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | sql   | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set

mysql> explain select * from `sql`;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | sql   | ALL  | NULL          | NULL | NULL    | NULL |   24 |       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set
mysql> select * from `sql` where id=1 order by (select 1 union select 2);
+----+------+
| id | new  |
+----+------+
|  1 | test |
+----+------+
1 row in set

mysql> select * from `sql` where id in (1,2) order by (select 1 union select 2);
1242 - Subquery returns more than 1 row
mysql> select * from `sql` order by (select 1 union select 2);
1242 - Subquery returns more than 1 row
mysql> 

可以看到 type  为 const 的时候不会报错。

百度到 type 各个值的含义

type=const表示通过索引一次就找到了;  
type=all,表示为全表扫描; 
type=ref,因为这时认为是多个匹配行,在联合查询中,一般为REF。

然后继续来看表结构

这里id 为主键,那么我们把id主键去掉,在执行上面的语句。

mysql> select * from `sql` where id=1 order by (select 1 union select 2);
1242 - Subquery returns more than 1 row
mysql> explain select * from `sql` where id=1;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | sql   | ALL  | NULL          | NULL | NULL    | NULL |   24 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set

结果就显示了错误。

结论:

      type为const,索引一次就能找到结果的查询会自动忽略order by 的排序错误,直接查询到结果。

 

以上是关于MYSQL order by 排序的一个小问题探究的主要内容,如果未能解决你的问题,请参考以下文章

Mysql Order By 字符串排序,mysql 字符串order by

mysql order by无效问题

sql order by,desc和limit使用(mysql)

MySQL中order by排序时,数据存在null咋办

MySQL order by关键字详解,order by排序

mysql order by 多个字段