设为首页 加入收藏

TOP

使用rowid和rownum获取记录时要注意的问题(二)
2015-07-24 10:44:57 来源: 作者: 【 】 浏览:3
Tags:使用 rowid rownum 获取 记录 时要 注意 问题
的第10条记录(0->9)
如果我们要获取test1表中的前5条记录,那么可以用如下的方法:
SQL> select object_id,object_name from test1 where rownum<=5;
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 44 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ#
或者

SQL> select object_id,object_name from test1 where rownum!=6;
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 44 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ#
对于第一种写法,大家都可以理解,那么为什么rownum!=6这个条件,返回的也是前5条记录呢?是不是觉得不可思议,7-10条记录也满足!=6啊,为什么不会显示呢?
来看一下官方关于rowid机制的解释:

1 Oracle executes your query.

2 Oracle fetches the first row and calls it row number 1.

3 Have we gotten past row number meets the criteria? If no, then Oracle discards the row, If yes, then Oracle return the row.

4 Oracle fetches the next row and advances the row number (to 2, and then to 3, and then to 4, and so forth).

5 Go to step 3.


当你使用rownum作为查询条件是,Oracle的SQL引擎总是会先去找row number 1这条记录,如果没有找到,那么就直接丢弃这些row,直到找到为止,然后才会有row number 2,row number 3……不断地循环这个过程,直到结束不符合条件为止
在第2个查询中,由于rownum=1符合了!=6这个条件,那么会依次fetch下去,直到取到了rownum=5,都是符合的记录,然后就会返回一个结果,而由于中间断档了,那么当找到第6条记录的时候,显然不符合!=6这个条件,那么刚才的一轮循环就结束了,而之后的第7条记录,由于其中不再包含row numer 1这个必要条件,因此直接就丢弃了后面的查询,也就是说,8-10条记录也不会再去fetch了,因为没有一条可以获取到rownum=1
同样的,当我们要获取后5条记录,即5 SQL> select rownum,object_id,object_name from test1 where rownum>5 and rownum <11;
no rows selected
为什么呢?原因刚才已经解释过了,由于rownum>5中首先就排除掉了rownum=1这条记录,因此就直接丢弃这些行,也就没有返回结果了,也就是一直去找row number 1,但永远也找不到(因为被条件排除掉了),即使把rownum<11这个条件写在前面,结果也是一致的,注意这里连接条件用的是and,如果用or那就相当于把rownum>5这个条件忽略了,是会有结果的
SQL> select object_id,object_name from test1 where rownum<11 or rownum>5;
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 44 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ# 3 I_OBJ# 25 PROXY_ROLE_DATA$ 39 I_IND1 51 I_CDEF2 26 I_PROXY_ROLE_DATA$_1
10 rows selected.

即使使用between ... and ...也是不行的,看执行结果:
SQL> select object_id,object_name from test1 where rownum between 0 and 5;
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 44 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ#
SQL> select object_id,object_name from test1 where rownum between 1 and 5;
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 44 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ#
SQL> select object_id,object_name from test1 where rownum between 6 and 10;

no rows selected
between0和1都是包含有rownum=1的,因此有结果,而between 6就相当于直接rownum>5,把rownum=1排除掉了,所以就无结果

由于rownum的这个伪列的特殊性,因此在我们书写SQL语句时,尤其是写分页代码的时候,必须使用子查询来获取后5条记录,如:
SQL> select b.object_id,b.object_name from (select rownum rn,a.* from test1 a where rownum<11) b where rn>5;
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 3 I_OBJ# 25 PROXY_ROLE_DATA$ 39 I_IND1 51 I_CDEF2 26 I_PROXY_ROLE_DATA$_1
当然,我们也可以用rowid来直接获取后5条记录,因为rowid没有rownum那样的特殊要求,但实际操作起来,是非常不方便的,实际环境中也没有这样的用法,rowid难以记忆也不方便书写
SQL> select object_id,object_name from test1 where rowid>to_char('AAAM+rAAGAAAACUAAE') and rowid<=to_char('AAAM+rAAGAAAACUAAJ');
OBJECT_ID OBJECT_NAME ---------- ------------------------------ 3 I_OBJ# 25 PROXY_ROLE_DATA$ 39 I_IND1 51 I_CDEF2 26 I_PROXY_ROLE_DATA$_1
总结:
rowid通常不直接用于SQL代码中,主要是给索引使用的,通过索引查找rowid,再更具rowid回表取数据,使Oracle 数据库完成高效的数据检索,而rownum则经常用在数据库的应用代码中,尤其是对分页数据的过滤,但使用的时候必须要注意rownum的特性,切忌跳过对rownum=1的获取而造成无结果集的问题
首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇改变Eclipse中代码字体大小 下一篇oracle数组

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·在 Redis 中如何查看 (2025-12-26 03:19:03)
·Redis在实际应用中, (2025-12-26 03:19:01)
·Redis配置中`require (2025-12-26 03:18:58)
·Asus Armoury Crate (2025-12-26 02:52:33)
·WindowsFX (LinuxFX) (2025-12-26 02:52:30)