在 Oracle 中,如果未指定“order by”子句,则选择查询的默认行顺序是什么。
是吗
- 插入行的顺序
- 根本没有默认排序
- 以上都不是。
根据 Tom Kyte 的说法:“除非并且直到您在查询中添加“order by”,否则您不能对返回的行的顺序说任何话。好吧,除了“您不能依赖返回的行的顺序”之外。
请在 asktom.com 上查看此问题。
至于ROWNUM,它在物理上并不存在,所以不能“释放”。ROWNUM 是在从表中检索到记录后分配的,这就是为什么“WHERE ROWNUM = 5”总是无法选择任何记录的原因。
@ammoQ:您可能想阅读这篇关于 GROUP BY 订购的 AskTom 文章。简而言之:
Query 中的 Group By 子句是否保证输出数据将按 Group By 列排序,即使没有 Order By 子句?
我们说...
绝对不,
它从来没有,它从来没有,它永远不会。
没有明确的默认排序。出于显而易见的原因,如果您创建一个新表,插入几行并执行没有“where”子句的“select *”,它将(很可能)按照插入的顺序返回行。
但是你永远不应该依赖默认订单的发生。如果您需要特定的订单,请使用“order by”子句。例如,在最高 9i 的 Oracle 版本中,执行“分组依据”也会导致行按组表达式 (*) 排序。在 10g 中,这种行为不再存在!因此,升级 Oracle 安装给我带来了一些工作。
(*) 免责声明:虽然这是我观察到的行为,但从未得到保证
已经说过,当您没有指定 ORDER BY 子句时,Oracle 可以按照它想要的任何顺序为您提供行。当您不指定 ORDER BY 子句时,推测订单将是什么是没有意义的。在你的代码中依赖它,是一个“职业限制举措”。
一个简单的例子:
SQL> create table t as select level id from dual connect by level <= 10
2 /
Tabel is aangemaakt.
SQL> select id from t
2 /
ID
----------
1
2
3
4
5
6
7
8
9
10
10 rijen zijn geselecteerd.
SQL> delete t where id = 6
2 /
1 rij is verwijderd.
SQL> insert into t values (6)
2 /
1 rij is aangemaakt.
SQL> select id from t
2 /
ID
----------
1
2
3
4
5
7
8
9
10
6
10 rijen zijn geselecteerd.
这只是在简单的删除+插入之后。还有许多其他可以想象的情况。并行执行、分区、索引组织表等等。
底线,正如 ammoQ 所说的那样:如果您需要对行进行排序,请使用 ORDER BY 子句。
除非您指定,否则您绝对不能依赖任何排序order by
。特别是对于 Oracle,我实际上已经看到完全相同的查询(没有连接),在几秒钟内彼此运行两次,在一个临时没有更改的表上,返回一个完全不同的顺序。当结果集很大时,这似乎更有可能。
Rob van Wijk 提到的并行执行可能解释了这一点。另请参阅 Oracle 的Using Parallel Execution文档。
它受索引的影响,如果有索引,它会返回一个升序,如果没有任何索引,它会返回插入的顺序。
您可以使用 CREATE TABLE 语句的 ORGANIZATION 子句通过 INSERT 修改数据存储到表中的顺序
虽然,它应该是 rownnum (你的 #2),但它真的不能保证,你不应该 100% 相信它。
我相信它使用了 Oracle 的隐藏 Rownum 属性。
所以你的#1 可能是正确的,假设没有删除可能已经释放 rownums 供以后使用。
编辑:正如其他人所说,你真的不应该依赖这个,永远。除了删除之外,还有许多不同的条件会影响默认排序行为。