SQL 行返回顺序

Posted

技术标签:

【中文标题】SQL 行返回顺序【英文标题】:SQL row return order 【发布时间】:2012-05-12 04:35:20 【问题描述】:

直到最近我开始每天使用 SQL,我才很少使用它。我注意到如果没有使用“order by”子句:

    在选择表的一部分时,返回的行似乎与当我选择整个表时出现的顺序相同 从连接中选择返回的行的顺序似乎是由连接的最左边的成员决定的。

这种行为在最常见的数据库(mysql、Oracle、PostgreSQL、Sqlite、Sql Server)中是可以依赖的标准行为吗? (我什至不知道是否可以在 sqlite 中真正指望它)。如果是这样,它的尊重程度有多严格(例如,如果一个人使用“分组依据”,那么各个组是否都会有这种排序)?

【问题讨论】:

What is MySQL row order for "SELECT * FROM table_name;"?的可能重复 【参考方案1】:

如果查询中不包含 ORDER BY 子句,则返回的行顺序未定义。

虽然某些 RDBMS 会在某些情况下以特定顺序返回行,即使省略了 ORDER BY 子句,但绝不应依赖这种行为。

【讨论】:

【参考方案2】:

第 20.2 节 ,小节“一般规则” SQL-92 specification:

4) 如果 没有指定,那么 Q 的行是依赖于实现的。

【讨论】:

这仅涵盖了cursors的问题,但对于不是通过游标获得的查询结果也是如此。【参考方案3】:

如果您想订购,请附上ORDER BY。如果你不包含ORDER BY,你是在告诉 SQL Server:

我不在乎你返回行的顺序,只返回行

既然你不在乎,SQL Server 将决定如何返回它认为可能是最有效的行现在(或根据上次计划此特定查询已缓存)。因此,您不应依赖您观察到的行为。它可以从一次查询运行到下一次查询,包括数据更改、统计信息更改、索引更改、服务包、累积更新、升级等等等等。

【讨论】:

+1 : 和并行性(也暗示,并发负载)。【参考方案4】:

对于 PostgreSQL,如果您省略 ORDER BY 子句,您可以在数据库未被修改的情况下运行完全相同的查询 100 次,并在中间以与其他顺序不同的顺序运行一次。事实上,每次运行的顺序可能不同。

可能发生这种情况的一个原因是,如果选择的计划涉及对表堆的顺序扫描,并且已经对该表的堆进行了 seqscan,那么您的查询将在其他扫描已经存在的任何点开始扫描at,以减少对磁盘访问的需求。

正如其他答案所指出的,如果您希望数据按特定顺序排列,请指定该顺序。 PostgreSQL 会在选择计划时考虑请求的顺序,并且可能会使用按该顺序提供数据的索引,如果这样比以其他方式获取行然后对它们进行排序更便宜。

GROUP BY不保证订单; PostgreSQL 可能对数据进行排序以进行分组,或者它可能使用哈希表并按照哈希算法生成的数字的顺序返回行(即,相当随机)。这可能会从一次运行到下一次发生变化。

【讨论】:

【参考方案5】:

当我还是一名 DBA 时,我一直惊讶于 SQL 的这个特性经常被认为是古怪的。考虑一个针对文本文件运行并产生一些输出的简单程序。如果程序永远不会改变,数据永远不会改变,那么您会期望输出永远不会改变。

至于这个:

如果查询中不包含 ORDER BY 子句,则返回的行顺序未定义。

不完全正确 - 在我曾经使用过的每个 RDBMS(Oracle、Informix、SQL Server、DB2 等等)上,DISTINCT 子句也与 ORDER BY 具有相同的效果,因为查找唯一值涉及排序依据定义。

编辑(2014 年 6 月 2 日):

创建一个简单的表格

对于 DISTINCT 和 ORDER BY,计划和成本都是相同的,因为表面上要执行相同的操作

毫不奇怪,效果是一样的

【讨论】:

在 PostgreSQL 中 有时 会这样做;根据有关查询的许多详细信息和优化器成本因素,它可能会使用排序来查找唯一值并按排序顺序返回行。有时它可能会发现哈希表会更快,并且唯一值将按照其哈希值的顺序排列,除非您指定了ORDER BY 子句。我怀疑 PostgreSQL 是唯一使用哈希表更快的产品,或者如果没有请求订单则以最快的方式返回结果。 SQL Server 也可以使用散列来确定不同的项目。只是证明没有ORDER BY,你不能依赖任何ORDER 我从未说过可以(或应该)依赖它。很简单,如果使用 values,重复数据删除将根据定义生成一个排序列表。显然,哈希会产生不同的排序结果。 您的回答清楚地表明“查找唯一值涉及按定义排序。”。这是错误的。例如在 SQL Server CREATE TABLE T(X INT);INSERT INTO T SELECT number%2 FROM master..spt_values;SELECT DISTINCT X FROM T 上测试执行计划是 like this。没有排序操作。输出可能会或可能不会被订购,对我来说是0,1,-1 你是认真的吗?查看执行计划 - 它使用 hash。没有 ORDER BY 的行的顺序未定义的基本前提是无稽之谈。这仅取决于实施。查看接受的答案中的 SQL 规范。

以上是关于SQL 行返回顺序的主要内容,如果未能解决你的问题,请参考以下文章

jdbc的executeBatch()返回正确的行计数

如何:Oracle 解析函数返回行

为啥 SQL 查询的结果没有按我期望的顺序返回?

如何从 T-SQL 存储过程返回表

让sql语句不排序,按照in语句的顺序返回结果

Oracle sql%rowcount 返回影响行数;sql server @@RowCount返回影响行数