我们知道,rowid和rownum在Oracle中都是可以被当做伪劣使用的,主要用来定位表中特定的记录,但它们是有区别的,rowid是和行记录的物理地址对应的,而rownum则不是,是通过返回的记录集来判断首条记录,即rownum=1的记录,然后再去fetch之后的记录,rownum=2、rownum=3……,以此类推。下面来看实验:
SQL> conn zlm/zlm
Connected.
SQL> create table test1 as select object_id,object_name from dba_objects where rownum col object_name for a30
SQL> select * from test1;
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.
用*来表示全部列,此时并不会显示出rowid,rownum这2个伪列,这也就是“伪列”这个名词的由来,是假的,fake的,我们可以使用它,但并不作为数据存储在表中
SQL> select rowid,rownum,object_id,object_name from test1;
ROWID ROWNUM OBJECT_ID OBJECT_NAME
------------------ ---------- ---------- ------------------------------
AAAM+rAAGAAAACUAAA 1 20 ICOL$
AAAM+rAAGAAAACUAAB 2 44 I_USER1
AAAM+rAAGAAAACUAAC 3 28 CON$
AAAM+rAAGAAAACUAAD 4 15 UNDO$
AAAM+rAAGAAAACUAAE 5 29 C_COBJ#
AAAM+rAAGAAAACUAAF 6 3 I_OBJ#
AAAM+rAAGAAAACUAAG 7 25 PROXY_ROLE_DATA$
AAAM+rAAGAAAACUAAH 8 39 I_IND1
AAAM+rAAGAAAACUAAI 9 51 I_CDEF2
AAAM+rAAAACU 10 26 I_PROXY_ROLE_DATA$_1
10 rows selected.
把列名全部显示指定,可以看到,rowid和rownum这两列的内容也都显示了。那我们能不能用rowid列来作为查找条件呢?当然是可以的,但前提是你要知道rowid值是怎么分布的
SQL> select rowid,object_id,object_name from test1 where rowid col name for a45
SQL> select file#,name from v$datafile;
FILE# NAME
---------- ---------------------------------------------
1 /u01/app/oracle/oradata/ora10g/system01.dbf
2 /u01/app/oracle/oradata/ora10g/undotbs01.dbf
3 /u01/app/oracle/oradata/ora10g/sysaux01.dbf
4 /u01/app/oracle/oradata/ora10g/users01.dbf
5 /u01/app/oracle/oradata/ora10g/example01.dbf
zlm用户默认的表空间就是zlm,其对应的数据文件就是zlm01.dbf,可以看到,
我们还可以用Oracle提供的来根据rowid的值来获取object_id#,rfile#,block#,row#这些具体的值:
SQL> select dbms_rowid.('AAAM+rAAGAAAACUAAJ') object_id#,dbms_rowid.('AAAM+rAAGAAAACUAAJ') rfile#,dbms_rowid.('AAAM+rAAGAAAACUAAJ') block#,dbms_rowid.('AAAM+rAAGAAAACUAAJ') row# from dual;
OBJECT_ID# RFILE# BLOCK# ROW#
--------------- ---------- ---------- ----------
test1表中第10行记录就是
如果我们要获取test1表中的前5条记录,那么可以用如下的方法:
SQL> select object_id,object_name from test1 where rownum 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机制的解释:
当你使用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
Oracle中rownum和rowid的理解
Oracle rowid
Oracle入门基础教程:rowid详解
Oracle 中ROWNUM用法总结,ROWNUM 与 rowid 区别
rowid走索引之嫌疑犯抓获
Oracle利用rownum和rowid分页
Oracle 10g 中的ROWID详解
更多详情见请继续阅读下一页的精彩内容: