SQL语句逻辑执行过程和相关语法详解(3)

由于数据无序,导致检索数据时都是按照存储时的物理顺序进行访问,如此检索得到的数据���都是随机而不保证任何顺序的,除非指定了ORDER BY子句。而使用ORDER BY查询得到的结果,它因为有序而不满足集合的概念。实际上ORDER BY生成的是一个游标结果。了解SQL的人,都知道能不用游标就尽量不用游标,因为它的效率相比符合集合概念的SQL语句来说,要慢很多个数量级。但也不能一棍子将其打死,因为有时候使用游标确实能比较容易达到查询目标。

SQL中没有使用ORDER BY时,有不少子句的返回结果(虚拟表)都是随机的,因为实在没办法去保证顺序,但却又要求返回数据。例如直接进行SELECT * from t; ,再例如TOP/LIMIT子句。

纵观整个SQL的各个环节,不难发现很多时候获取随机行数据是不应该的,因为这种不确定性,让我们操作数据时显得更出乎意料、更危险因此,除非不得不显示随机数据,标准SQL都会通过一些手段让获取随机数据的行为失败,而且在可能获取随机数据的时候,一般都会给出相关的建议和提示。

MySQL、mariadb之所以和sql server、oracle的语法相差那么大,归根结底就是对待关系型数据库的范式要求和随机数据的态度不同。MySQL、mariadb总是"偷奸耍滑",在本无法满足关系型数据库范式的时候,它们总是挑选一个随机单行数据出来,让返回结果满足范式要求,最典型的就是group by的处理方式不过MySQL从5.7.5版本开始,已经逐渐走向规范化了。

这里并非是要否认mysql、mariadb的设计模式,正所谓每个数据库系统都有自己对标准SQL的扩展方式,MySQL只是走了一条和标准SQL不同的路而已。而且关系模型的范式本就是人为定义的,为何不能违反呢?甚至可以说,表所满足的范式越强,检索表时的性能越低,nosql就没有关系模型的范式要求。

在后文,将在多处分析标准SQL为什么不允许某些语法,同时还会提到MySQL和mariadb是如何"偷奸耍滑"的。

1.6 关于TOP(或LIMIT)和ORDER BY

TOP和LIMIT是限制输出行数量,它们挑选数据行时是随机的(根据物理访问顺序),所以得到的结果也是随机的。因此,建议TOP/LIMIT和ORDER BY一起使用。但即使如此,仍是不安全的。例如,ORDER BY的列中有重复值,那么TOP/LIMIT的时候如何决定获取哪些行呢?见如下LIMIT的示例(TOP也一样):

MariaDB [test]> select * from Student order by age;
+------+----------+------+--------+
| sid  | name    | age  | class  |
+------+----------+------+--------+
|    6 | zhaoliu  |  19 | Java  |
|    4 | lisi    |  20 | C#    |
|    8 | sunba    |  20 | C++    |
|    3 | zhangsan |  21 | Java  |
|    5 | wangwu  |  21 | Python |
|    1 | chenyi  |  22 | Java  |
|    7 | qianqi  |  22 | C      |
|    2 | huanger  |  23 | Python |
|    9 | yangjiu  |  24 | Java  |
+------+----------+------+--------+
 
MariaDB [test]> select * from Student order by age limit 9;
+------+----------+------+--------+
| sid  | name    | age  | class  |
+------+----------+------+--------+
|    6 | zhaoliu  |  19 | Java  |
|    4 | lisi    |  20 | C#    |
|    8 | sunba    |  20 | C++    |
|    3 | zhangsan |  21 | Java  |
|    5 | wangwu  |  21 | Python |
|    1 | chenyi  |  22 | Java  |
|    7 | qianqi  |  22 | C      |
|    2 | huanger  |  23 | Python |
|    9 | yangjiu  |  24 | Java  |
+------+----------+------+--------+

从两次查询结果中看到,即使都是对age进行升序排列,但age=20的两行前后顺序不一致,age=22的行顺序也不一致。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/90c3b57f9b6508b170ad70d479052a49.html