• 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 的排序错误,直接查询到结果。

  • 相关阅读:
    中阶 d04.1 xml解析
    中阶 d04 xml 概念及使用
    中阶 d03.5 (正篇)完整的Dao 操作数据库
    中阶d03.4 JDBC_DAO
    中阶d03.3 JDBC_CURD_Util --- 使用 junit执行单元测试(增删改查)
    单元测试 junit
    idle中上传jar包并使用的方法
    intelij idea 和 eclipse 使用上的区别
    中阶d03.2 JDBC联合properties使用,通过读取本地配置文件为代码传递参数
    swift init 初始化
  • 原文地址:https://www.cnblogs.com/depycode/p/6265938.html
Copyright © 2020-2023  润新知