`
xinklabi
  • 浏览: 1586912 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
文章分类
社区版块
存档分类
最新评论

Oracle RowID与RowNum的区别

 
阅读更多

Rowid和Rownum对于数据库开发人员来说基本很少用到,因为在企业数据库开发中大多都是进行数据批处理,但是对于其他数据库人员来说还是会用到的。
rowid和rownum都是虚列,但含义完全不同。rowid是物理地址,用于定位oracle中具体数据的物理存储位置,而rownum则是sql的输出结果排序。通俗的讲:rowid是相对不变的,rownum会变化,尤其是使用order by的时候。

 

rowid 用于定位数据表中某条数据的位置,是唯一的、也不会改变

 

rownum 表示查询某条记录在整个结果集中的位置, 同一条记录查询条件不同对应的 rownum 是不同的而 rowid 是不会变的

   

例如有如下一张表 :USER  

name

age

张三

20

李四

22

王五

23

 

当执行查询 : select  rowid ,rownum ,name,age   from USER order by age asc 时结果如下:  

rowid

rownum

name

age

AAAOWhAAQAAALgdAAa

1

张三

20

AAAOWhAATAAALp7AAd

2

李四

22

AAAOWhAATAAALp7AAe

3

王五

23

   

当执行查询 : select  rowid ,rownum ,name,age   from USER order by age desc 时结果如下:  

rowid

rownum

name

age

AAAOWhAATAAALp7AAe

1

王五

23

AAAOWhAATAAALp7AAd

2

李四

22

AAAOWhAAQAAALgdAAa

3

张三

21

 

ROWID: 
1、为什么使用ROWID   

ORACLE把ROWID作为B-树和其内部算法标示ROW的唯一标示。在ORACLE8以前的版本中,ROWID标示FILE、BLOCK,ROW NUMBER,只用一个数字代表FILE号。

在ORACLE8中,一个DATAFILE有两个数字代表:

1.)一个绝对值,是整个数据库唯一的。可以看DBA_DATA_FILES中的FILE_ID。

 

[java] view plaincopy
 
  1. SQL> SELECT FILE_ID FROM DBA_DATA_FILES;  
  2.    FILE_ID  
  3. ----------  
  4.          4  
  5.          3  
  6.          2  
  7.          1  

 

 

2.)一个相对值,在TABLESPACE中是唯一的,可以看DBA_DATA_FILES中的RELATIVE_FNO。

 

[java] view plaincopy
 
  1. SQL> SELECT RELATIVE_FNO FROM DBA_DATA_FILES;  
  2. RELATIVE_FNO  
  3. ------------  
  4.            4  
  5.            3  
  6.            2  
  7.            1  


新的ROWID使用相对值,所以必须存放SEGMENT的标示,否则就会混淆。所以ORACLE8在ROWID中加入对象的SEGMENT号,用来标示TABLE或者PARTITION。

2、ROWID的结构  

 

使用base-64代码,包括a-z,A-Z,0-9,+,-。一共18位。   1-6位:代表OBJECT   7-9位:文件相对值   10-15:文件中的BLOCK   16-18:BLOCK中的SLOT值

  3、TABLESPACE-Relative寻址方式  使用的是TABLESPACE-Relative寻址方式,多个文件可以有相同的相对值,因为它  们属于不同的TABLESPACE,所以不能从新的ROWID得到绝对地址,但是这没有问题  ,因为当要处理某个OBJECT时,已经能确定它属于哪个TABLESAPCE了。在TABLES   PACE中,文件相对值是唯一的,所以ROWID还是可以唯一标示一个OBJECT。TABLE   SPACE-Relative寻址方式是ORACLE8中支持超大数据库的关键技术。

  4、DATA OBJECT NUMBER   DATA OBJECT NUMBER用于指示SEGMENT,所有SEGMENT都有DATA OBJECT NUMBER,存放在每个DATA BLOCK中,而且不重复。

  最开始的时候,DBA_OBJECTS.OBJECT_ID=DBA_OBJECTS.DATA-OBJECT_ID,但是在上述情况下DATA- OBJECT_ID会在如下情况下增加   TRUNCATE TABLE   MOVE PARTITION   ORACLE会检查ROWID中的DATA OBJECT NUMBER和BLOCK中的DATA OBJECT NUMBER,保证他们之间的版本是一致的。   ORACLE也使用DATA OBJECT NUMBER以确保ROLLBACK的纪录和最新的SEGMENT纪录一致。   要注意的是DATA OBJECT NUMBER不是OBJECT 的标志

    5、RESTRICTED ROWID   ORACLE7的ROWID格式是   1-8位:BLOCK NUMBER   9-12位:ROW NUMBER   13-16位:FILE NUMBER   ORACLE8支持短的、旧格式的ROWID,作用是  对NOPARTITION TABLE的INDEX ENTRY   对PARTITION TABLE的LOCAL INDEX ENTRY   ROW Piece CHain pointer   受限ROWID的内部存放是6BYTE,   4BYTE=DATA BLOCK NUMBER   2BYTE=ROW NUMBER   这就是说,INDEX ENTRY使用6BYTE存放该ROWID,这对大多数INDEX足够了。但是这种短ROWID不能使用在PATITION TABLE的GLOBAL INDEX上,因为PARTITION可能跨TABLESPACE。显示这种ROWID依然是18位的

  6、扩展的ROWID   ORACLE在内部存放时候是10 BYTE,包括(DATA OBJECT NUMBER,DATA BLOCK NU   MBER,ROW NUMBER)   ORACLE8使用扩展的ROWID:   PARTITION TABLE 的GLOBAL INDEX   SERVER 算法   扩展的ROWID在SELECT时,依然是18位的显示,存放在ROWID字段中。

  7、在ORACLE8中使用 ORACLE7的ROWID   从ORACLE8的DB中查询ORACLE7的ROWID时候,ROWID返回的是ORACLE7的格式,也可以用在WHERE语句中。  从ORACLE7的DB中查询ORACLE8的ROWID时候,ROWID返回的是ORACLE8的格式,也可以用在WHERE语句中,但是不能存放在ROWID字段中。但是你要用DBMS_ROWID 包来解释之。   如果包含扩展的ORACLE8 ROWID,这不能把ORACLE8的数据IMPORT到ORACLE7中。从ORACLE7中可以IMPORT到ORACLE8中。

   8、APPLICATION的移植问题   一般程序的移植应该没有问题。只有在下面情况下才考虑移植问题:  application使用了rowid   table包括ROWID类型的字段   如果程序有如下情况,必须使用DBMS_ROWID包:  自己组合ROWID   自己分解ROWID   如果仅仅是传递ROWID到变量、或者仅仅做为一个整体使用,则可以不受影响。

    9、数据的移植问题   无论使用EXPORT/IMPORT还使用移植工具,ORACLE7中的ROWID字段到了ORACLE8中就自动扩展。如果在某个字段内容中包含ROWID,则必须手工用DBMS_ROWID包来转换。

  10、DBMS_ROWID包  由$ORACLE_HOME/rdbms/admin/dbmsutil.sql创建,其实在catproc.sql中包含着。提供处理ROWID的一些函数。   ROWID_CREATE   ROWID_INFO   ROWID_TYPE   ROWID_OBJECT   ROWID_RELATIVE_FNO   ROWID_BLOCK_NUMBER   ROWID_TO_ABSOLUTE_FNO   ROWID_TO_EXTENDED   ROWID_TO_RESTRICTED   ROWID_VERIFY

     DBMS_ROWID.ROWID_TO_EXTENDED   (old_rowid in ROWID,   schema_name in varchar2,   object_name in varchar2,   conversion_type in number   )   RETURN ROWID;   转换受限rowid到扩展rowid,用于转换旧的ROWID到ORACLE8的格式。

    DBMS_ROWID.ROWID_TO_RESTRICTED 转换扩展的ROWID到受限的ROWID。

  DBMS_ROWID.ROWID_VERIFY   判断一个受限的ROWID是否可以转换到扩展的格式

    DBMS_ROWID.ROW_INFO   用于解释ROWID,可以得到DATA OBJECT NUMBER,RELATIVE FILE NUMBER,BLOCK NUMBER和ROW NUMBER。

  DBMS_ROWID.CREATE   生成ROWID。

ROWNUM:

在Oracle中,要按特定条件查询前N条记录,用个rownum就搞定了。 select * from emp whererownum<= 5 而且书上也告诫,不能对rownum用">",这也就意味着,如果你想用 select * from emp whererownum> 5 则是失败的。要知道为什么会失败,则需要了解rownum背后的机制: 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>不会成功,因为在第三步的时候查询出的行已经被丢弃,第四步查出来的rownum仍然是1,这样永远也不会成功。

同样道理,rownum如果单独用=,也只有在rownum=1时才有用。

 

对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,而且rownum不能以任何表的名称作为前缀。  举例说明:例如表:student(学生)表,表结构为: ID       char(6)      --学号 name    VARCHAR2(10)   --姓名 create table student (ID char(6), name VARCHAR2(100)); insert into sale values('200001',‘张一’); insert into sale values('200002',‘王二’); insert into sale values('200003',‘李三’); insert into sale values('200004',‘赵四’); commit; (1) rownum对于等于某值的查询条件如果希望找到学生表中第一条学生的信息,可以使用rownum=1作为条件。但是想找到学生表中第二条学生的信息,使用rownum=2结果查不到数据。因为rownum都是从1开始,但是1以上的自然数在rownum做等于判断是时认为都是false条件,所以无法查到rownum= n(n>1的自然数)。 SQL> selectrownum,id,name from student whererownum=1;(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标) SQL> selectrownum,id,name from student whererownum=1;    ROWNUMID     NAME ---------- ------ ---------------------------------------------------          1 200001 张一 SQL> selectrownum,id,name from student whererownum=2;    ROWNUMID     NAME ---------- ------ --------------------------------------------------- (2)rownum对于大于某值的查询条件    如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的,原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum> n(n>1的自然数)这种条件依旧不成立,所以查不到记录 SQL> selectrownum,id,name from student whererownum>2;ROWNUMID     NAME ---------- ------ --------------------------------------------------- 那如何才能找到第二行以后的记录呀。可以使用以下的子查询方法来解决。注意子查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询的列还是主查询的列。 SQL>select * from(selectrownumno ,id,name from student) where no>2;         NO ID     NAME ---------- ------ ---------------------------------------------------          3 200003 李三          4 200004 赵四 SQL> select * from(selectrownum,id,name from student)whererownum>2;    ROWNUMID     NAME ---------- ------ --------------------------------------------------- (3)rownum对于小于某值的查询条件如果想找到第三条记录以前的记录,当使用rownum<3是能得到两条记录的。显然rownum对于rownum<n((n>1的自然数)的条件认为是成立的,所以可以找到记录。 SQL> selectrownum,id,name from student whererownum<3;    ROWNUMID     NAME ---------- ------ --------------------------------------------------- 1 200001 张一         2 200002 王二综上几种情况,可能有时候需要查询rownum在某区间的数据,那怎么办呀从上可以看出rownum对小于某值的查询条件是人为true的,rownum对于大于某值的查询条件直接认为是false的,但是可以间接的让它转为认为是true的。那就必须使用子查询。例如要查询rownum在第二行到第三行之间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询中判断新的rownum的别名列大于等于二的记录行。但是这样的操作会在大数据集中影响速度。 SQL> select * from (selectrownumno,id,name from student whererownum<=3 ) where no >=2;         NO ID     NAME ---------- ------ ---------------------------------------------------          2 200002 王二          3 200003 李三(4)rownum和排序 Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。 SQL> selectrownum,id,name from student order by name;    ROWNUMID     NAME ---------- ------ ---------------------------------------------------          3 200003 李三          2 200002 王二          1 200001 张一          4 200004 赵四可以看出,rownum并不是按照name列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。为了解决这个问题,必须使用子查询 SQL> selectrownum,id,name from (select * from student order by name);    ROWNUMID     NAME ---------- ------ ---------------------------------------------------          1 200003 李三          2 200002 王二          3 200001 张一          4 200004 赵四这样就成了按name排序,并且用rownum标出正确序号(小到大)

分享到:
评论

相关推荐

    rowid与rownum区别

    ORACLE 中ROWNUM用法总结!数据库管理员及程序开发员必看。

    oracle_SQL中rowid与rownum的使用

    在Oracle SQL中,`ROWID`和`ROWNUM`是两个非常重要的概念,它们在数据库查询和数据操作中起着至关重要的作用。本文将详细探讨这两个特性,包括它们的定义、用途以及如何在实际场景中有效利用它们。 一、ROWID详解 `...

    oracle_SQL中ROWID与ROWNUM的使用

    ### Oracle SQL中ROWID与ROWNUM的使用 #### ROWNUM 的使用——TOP-N 分析 在 Oracle SQL 中,`ROWNUM` 是一种特殊的伪列,用于标识查询结果集中的行编号。它常用于实现 TOP-N 查询,即返回结果集中满足特定条件的...

    Oracle学习笔记(rownum和rowid)

    Oracle学习笔记(rownum和rowid),有具体的代码案例讲解rownum和rowid

    oracle_SQL-rowid--rownum.zip_oracle

    **ROWID与ROWNUM的区别** - `ROWID`是物理地址,而`ROWNUM`是逻辑序列号。 - `ROWID`始终唯一,即使行被移动或复制,`ROWID`也会改变;`ROWNUM`则在每次查询时重新生成,不保证唯一性。 - `ROWID`可用于直接定位行...

    对于 Oracle 的 rownum 问题

    =),并非说用&gt;,&gt;=,=,between..and 时会提示SQL语法错误,而是经常是查不出一条记录来,还会出现似乎是莫名其妙的结果来,其实您只要理解好了这个 rownum 伪列的意义就不应该感到惊奇,同样是伪列,rownum 与 rowid ...

    rowid与rownumber

    rowid 与 rownumber 的介绍和应用 rowid 和 rownum 是 Oracle 数据库中的两个重要概念,对于数据库开发人员来说非常重要。下面我们将详细介绍 rowid 和 rownum 的概念、结构、应用场景等。 一、rowid 概念 rowid ...

    Oracle查询语句中rownum与rowid的不同之处分析

    本文主要是以实例形式介绍了Oracle查询中rownum与rowid的不同之处,以及以假设的方式为例,查询条件为rownum = 2,在查询出第一条记录时的具体内容的介绍。 在查询中,我们可以注意到,类似于 select xx from ...

    在oracle中灵活使用Rownum和rowId

    ### 在Oracle中灵活使用Rownum和RowId 在Oracle数据库中,`ROWNUM` 和 `ROWID` 是两个非常重要的概念,它们可以帮助我们在查询数据时实现更灵活的数据管理。本文将详细介绍这两个概念的区别及其使用方法,并通过...

    关于oracle的rownum

    另外,ROWNUM 与 ROWID 虽然都是伪列,但它们的存在方式是不一样的。ROWID 可以说是物理存在的,表示记录在表空间中的唯一位置 ID,在 DB 中唯一。只要记录没被搬动过,ROWID 是不变的。ROWID 相对于表来说又像表中...

    oracle rownum 学习

    Oracle ROWNUM学习 Oracle ROWNUM是Oracle系统顺序分配的行号,用于限制查询返回的总行数。ROWNUM是一个伪字段,不能以任何表的名称作为前缀。下面是对ROWNUM的详细讲解: 一、ROWNUM的基本用法 ROWNUM是一个伪...

    基于Oracle RowID实现批量数据的分页下载.pdf

    在获取某一页数据时,可以先查询上一页的最后一个RowID(即`StopKey`),然后在下次查询时,设置`WHERE RowID &gt; StopKey AND ROWNUM ,这样Oracle只会扫描大于`StopKey`的行,直到达到`pageSize`的数量,从而避免了...

    oracle-rownum用法

    Oracle ROWNUM 用法详解 ROWNUM 是 Oracle 系统中一个伪列,用于对查询返回的行进行编号,从 1 开始,每行递增 1。ROWNUM 可以用于限制查询返回的总行数,但需要注意的是,ROWNUM 不能以任何表的名称作为前缀。 ...

    Oracle DBA性能优化实践

    Hint.pdf Oracle中rowid与rownum的使用.pdf Oracle优化 之 索引.pdf Oracle优化器.pdf STATSPACK详解.pdf 学用ORACLE_AWR和ASH特性.pdf 执行计划.pdf

    ORACLE数据库中ROWNUM用法详解

    6. **ROWID与ROWNUM的区别**:ROWID是Oracle数据库中另一个伪列,它标识表中每行的物理位置,是表空间中记录的唯一标识。ROWID是物理存在的,不会因查询顺序改变而变化,可以作为查询条件,不会出现ROWNUM那样的问题...

    oracle的伪列与分页

    Oracle提供了一些内置的伪列供用户使用,如`ROWID`和`ROWNUM`等,这些伪列可以帮助开发人员更方便地进行查询、排序等操作。 #### 二、ROWID与ROWNUM详解 **ROWID:** - **定义**:ROWID是Oracle中用于唯一标识表中...

    oracle和db2的区别

    ### Oracle与DB2的主要区别 本文旨在探讨Oracle与DB2这两种主流关系型数据库管理系统(RDBMS)之间的关键差异。Oracle由甲骨文公司开发,而DB2则由IBM推出。两者均广泛应用于企业级环境,提供了强大的数据管理能力。...

Global site tag (gtag.js) - Google Analytics