ITPUB论坛 » Oracle开发 » rownum受不受order by影响的观察
新一届的微软MVP评选已经开始,欢迎各位推荐!
2008-7-5 21:20 gthboy
rownum受不受order by影响的观察

很多书上都写:rownum伪列不受order by子句影响,今天试了一下,发现不是那么简单的,呵呵。

[quote]SQL> create table t6 as select * from t5;

表已创建。

SQL> select constraint_name,constraint_type from user_constraints where table_na
me='T6';

未选定行[/quote]

表t6现在是一个没有约束的表

[quote]SQL> select rownum,rowid,t6.* from t6;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         1 AAAHROAAKAAAALkAAA          1          2
         2 AAAHROAAKAAAALkAAB          2          2
         3 AAAHROAAKAAAALkAAC          3          2
         4 AAAHROAAKAAAALkAAD          5          3
         5 AAAHROAAKAAAALkAAE          4          3
         6 AAAHROAAKAAAALkAAF          6          7
         7 AAAHROAAKAAAALkAAG          8          6

已选择7行。

SQL> select rownum,rowid,t6.* from t6 order by a;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         1 AAAHROAAKAAAALkAAA          1          2
         2 AAAHROAAKAAAALkAAB          2          2
         3 AAAHROAAKAAAALkAAC          3          2
         5 AAAHROAAKAAAALkAAE          4          3
         4 AAAHROAAKAAAALkAAD          5          3
         6 AAAHROAAKAAAALkAAF          6          7
         7 AAAHROAAKAAAALkAAG          8          6

已选择7行。

SQL> select rownum,rowid,t6.* from t6 order by a desc;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         7 AAAHROAAKAAAALkAAG          8          6
         6 AAAHROAAKAAAALkAAF          6          7
         4 AAAHROAAKAAAALkAAD          5          3
         5 AAAHROAAKAAAALkAAE          4          3
         3 AAAHROAAKAAAALkAAC          3          2
         2 AAAHROAAKAAAALkAAB          2          2
         1 AAAHROAAKAAAALkAAA          1          2

已选择7行。[/quote]

由上面可以看到,在普通字段上排序后,rownum的值与记录的rowid密切相关,它不受order by子句的影响。下面我们设置个主键再来看看

[quote]SQL> alter table t6 add constraint con_p_t6 primary key (a);

表已更改。

SQL> select rownum,rowid,t6.* from t6;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         1 AAAHROAAKAAAALkAAA          1          2
         2 AAAHROAAKAAAALkAAB          2          2
         3 AAAHROAAKAAAALkAAC          3          2
         4 AAAHROAAKAAAALkAAD          5          3
         5 AAAHROAAKAAAALkAAE          4          3
         6 AAAHROAAKAAAALkAAF          6          7
         7 AAAHROAAKAAAALkAAG          8          6

已选择7行。

SQL> select rownum,rowid,t6.* from t6 order by a;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         1 AAAHROAAKAAAALkAAA          1          2
         2 AAAHROAAKAAAALkAAB          2          2
         3 AAAHROAAKAAAALkAAC          3          2
         4 AAAHROAAKAAAALkAAE          4          3
         5 AAAHROAAKAAAALkAAD          5          3
         6 AAAHROAAKAAAALkAAF          6          7
         7 AAAHROAAKAAAALkAAG          8          6

已选择7行。

SQL> select rownum,rowid,t6.* from t6 order by a desc;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         1 AAAHROAAKAAAALkAAG          8          6
         2 AAAHROAAKAAAALkAAF          6          7
         3 AAAHROAAKAAAALkAAD          5          3
         4 AAAHROAAKAAAALkAAE          4          3
         5 AAAHROAAKAAAALkAAC          3          2
         6 AAAHROAAKAAAALkAAB          2          2
         7 AAAHROAAKAAAALkAAA          1          2

已选择7行。[/quote]

嘿嘿,与rowid紧密相关的rownum变成与order by相关了!再来看看普通字段

[quote]SQL> select rownum,rowid,t6.* from t6 order by b;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         1 AAAHROAAKAAAALkAAA          1          2
         2 AAAHROAAKAAAALkAAB          2          2
         3 AAAHROAAKAAAALkAAC          3          2
         4 AAAHROAAKAAAALkAAD          5          3
         5 AAAHROAAKAAAALkAAE          4          3
         7 AAAHROAAKAAAALkAAG          8          6
         6 AAAHROAAKAAAALkAAF          6          7

已选择7行。

SQL> select rownum,rowid,t6.* from t6 order by b desc;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         6 AAAHROAAKAAAALkAAF          6          7
         7 AAAHROAAKAAAALkAAG          8          6
         4 AAAHROAAKAAAALkAAD          5          3
         5 AAAHROAAKAAAALkAAE          4          3
         1 AAAHROAAKAAAALkAAA          1          2
         2 AAAHROAAKAAAALkAAB          2          2
         3 AAAHROAAKAAAALkAAC          3          2

已选择7行。[/quote]

看来,在普通字段上排序,rownum的值还是与记录的rowid紧密相关的。



结论:rownum伪列受不受order by排序的影响,要看我们order by什么字段。如果我们order by非主键字段,那么rounum是不受order by影响的;如果我们order by主键字段,那么rownum的值将受order by的影响!

2008-7-5 21:31 sunfly1983
看来以后用到rownum和order by的时候要小心了!
谢谢提醒啊!

2008-7-5 23:10 caizhuoyi
Oracle中的rownum是在取数据的时候产生的序号,对指定排序的数据去指定的rowmun行数据并不一定出现预期的结果。

SQL> select rownum,rowid,t6.* from t6 order by a desc;

    ROWNUM ROWID                       A          B          C
---------- ------------------ ---------- ---------- ----------
         7 AAAHROAAKAAAALkAAG          8          6
         6 AAAHROAAKAAAALkAAF          6          7
         4 AAAHROAAKAAAALkAAD          5          3
         5 AAAHROAAKAAAALkAAE          4          3
         3 AAAHROAAKAAAALkAAC          3          2
         2 AAAHROAAKAAAALkAAB          2          2
         1 AAAHROAAKAAAALkAAA          1          2
可以这样解决:
select rownum,t.* from (select rowid,t6.* from t6 order by a desc) t;
这样才能产生正确的结果。

2008-7-6 00:13 8193102
这个要看你的Oracle版本了,对于ORACLE9i中,官方网明确说明排序时受列的索引及非空有关系,并不是简单地说没有关系,对于Oracle9可以看看笔者的文章:
[url]http://blog.sina.com.cn/s/blog_511846a201008sbu.html[/url]

2008-7-6 07:24 jvkojvko
不明白

2008-7-6 09:40 gthboy
[quote]原帖由 [i]8193102[/i] 于 2008-7-6 00:13 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10868514&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]
这个要看你的Oracle版本了,对于ORACLE9i中,官方网明确说明排序时受列的索引及非空有关系,并不是简单地说没有关系,对于Oracle9可以看看笔者的文章:
[url=http://blog.sina.com.cn/s/blog_511846a201008sbu.html]http://blog.sina.com.cn/s/blog_511846a201008sbu.html[/url] [/quote]

知道了,只要order by的字段有not null约束,同时有索引,那么rownum的顺序就是依次递增。

2008-7-6 10:42 8193102
但是要注意,在10g下的机制还是有变化的,因为它们的优化原则不同.

2008-7-6 12:15 gthboy
[quote]原帖由 [i]8193102[/i] 于 2008-7-6 10:42 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10869628&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]
但是要注意,在10g下的机制还是有变化的,因为它们的优化原则不同. [/quote]

10g下有变化?怎么变化?

如果一个应用系统是基于9i开发的,使 用了rownum,那把数据迁移到10g上,程序执行结果会不会改变甚至出错啊? :surprise:

2008-7-7 10:40 gthboy
[quote]原帖由 [i]gthboy[/i] 于 2008-7-6 12:15 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10870029&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]


10g下有变化?怎么变化?

如果一个应用系统是基于9i开发的,使 用了rownum,那把数据迁移到10g上,程序执行结果会不会改变甚至出错啊? :surprise: [/quote]


这个问题,楼上老大再来讲讲呗

2008-7-7 10:43 wuhuaT
[quote]原帖由 [i]8193102[/i] 于 2008-7-6 10:42 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10869628&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]
但是要注意,在10g下的机制还是有变化的,因为它们的优化原则不同. [/quote]
是呀,升级了怎么整?愿闻其详.

2008-7-7 11:52 shiguibao
[quote]原帖由 [i]gthboy[/i] 于 2008-7-6 12:15 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10870029&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]


10g下有变化?怎么变化?

如果一个应用系统是基于9i开发的,使 用了rownum,那把数据迁移到10g上,程序执行结果会不会改变甚至出错啊? :surprise: [/quote]
不仅是rownum,如果是只group by 没有order by 都可能有问题

2008-7-7 21:46 8193102
不过可以略总结一下,
select rownum, t.*  from t.table where rownum=1 order by t.id;
select rownum, t.*  from t.table where rownum=1 order by t.id desc;


t.id是主键(通过非空),不过是9i还是10g的结果都是一样的,

某些情况下,实在不行,可以加上强制索引,由于9i和10g的优化器不同,所以不建议这样使用.
不知道10g是否还可以改回用9i的优化方法,

select rownum, t.*  from t.table where rownum<100 order by t.id;
此时就要看table的记录数了,在10g下这个100不是个确定数,少于一定比例可以rownum是从1开始的,有时候就是1条记录之差,可能就乱序了,

2008-7-8 02:38 newkid
不要依赖任何自然顺序,因为那是很靠不住的。

像这种写法不可取:
select rownum, t.*  from t where rownum<100 order by t.id;

必须改成这样:
select * from (select * from t order by t.id) where rownum<100;

2008-7-8 08:58 8193102
楼上的说得对,但是要知道,如果在9i下,这样写是没有问题的(9i在Oracle的官方网上我找到了相应的说明,只取前100条时,性能没有比它更好的),
如果在10g下是不能这么写的,它依赖于系统的优化策略

2008-7-8 09:37 nyfor
rownum 就是按照取得数据的顺序来进行编号的.

那么数据的提取顺序就成为了一个关键的问题. 当Oracle执行计划不走索引的时候, 数据的提取顺序就是按照 ROWID 大小物理顺序提取的, 如果 Oracle执行计划中有走索引的时候, 那么数据的提取是先读取索引, 因此其顺序就是按照索引中的顺序来的.

俺认为 Rownum 与 Order By 没有任何关系.

2008-7-8 09:59 feng2371
没有任何关系?没太明白

2008-7-8 10:04 nyfor
rownum 只与和数据读取顺序有关的执行计划有关, 而与 Order by 无关,
当然 Order by 可能会影响 Oracle 的执行计划, 但这不是说就和 Rownum 有关系.

2008-7-8 10:27 wilson2006
总之,rownum不是很保险,使用的时候要确保不出错,就要使用子查询。

2008-7-8 22:18 newkid
[quote]原帖由 [i]nyfor[/i] 于 2008-7-8 10:04 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10885431&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]
rownum 只与和数据读取顺序有关的执行计划有关, 而与 Order by 无关,
当然 Order by 可能会影响 Oracle 的执行计划, 但这不是说就和 Rownum 有关系. [/quote]

rownum如果和order by在同一层,那就不能理解为排序后的序号(因此是无关的)
如果像我这样写:
select rownum, t2.* from (select * from t order by t.id) t2 where rownum<100;
rownum就是排序后的序号。

2008-7-8 22:20 newkid
[quote]原帖由 [i]8193102[/i] 于 2008-7-8 08:58 发表 [url=http://www.itpub.net/redirect.php?goto=findpost&pid=10884544&ptid=1017338][img]http://www.itpub.net/images/common/back.gif[/img][/url]
楼上的说得对,但是要知道,如果在9i下,这样写是没有问题的(9i在Oracle的官方网上我找到了相应的说明,只取前100条时,性能没有比它更好的),
如果在10g下是不能这么写的,它依赖于系统的优化策略 [/quote]

select rownum, t2.* from (select * from t order by t.id) t2 where rownum<100;
这是典型的 TOP N 查询,在10g下不能这么写?是数据不对?还是效率太低?那你说该怎么写?

页: [1] 2


Powered by ITPUB论坛