ROWID(Oracle)- 有任何用途吗?

42

我的理解是,ROWID是查询结果中每一行的唯一值。

为什么我们需要ROWID?ORACLE已经有ROWNUM了。

有人在SQL查询中使用过ROWID吗?

6个回答

50

ROWID是一行的物理位置,因此它是定位行的最快方法,甚至比主键查找更快。因此,在某些事务类型中,选取某些行、存储其ROWIDs,然后稍后在对这些相同行进行DML时使用ROWIDs的where子句非常有用。

当我们使用WHERE CURRENT OF更新被锁定的行时,Oracle SELECT ... FOR UPDATE语法隐式地使用ROWID。同时,应用EXCEPTIONS INTO子句约束时引用EXCEPTIONS表(具有ROW_ID列)。这使我们能够快速识别违反约束的行。

后面那个例子指向另一种通用用途:当我们编写一些通用代码并需要一种机制来存储UIDs而不必考虑数据类型、复合键等。

另一方面,ROWNUM是一个伪列,标记给定结果集中的一行。它没有永久意义。

编辑

给定记录的ROWID在系统运行期间可能会发生变化,例如通过表重建。此外,如果删除一个记录,新记录可能会获得该ROWID。因此,ROWID不适合长期用作UID。但是在事务内部使用它们足够好。


14

我现在有一个例子。

假设你有一张没有主键的表,因此该表可能会有重复的行。那么如何删除重复的行但保留其中一条?

Oracle提供了ROWID作为主键的替代品。你可以编写一个关联查询语句来实现(在内部查询中按照行中的所有列进行分组,并取得每个组中最小的ROWID,在外部查询中删除该组中的其他行)。

例如:

SQL> select * from employees;

       SSN NAME
---------- ----------
         1 helen
         1 helen
         2 helen
         2 peter
        10 sally
        11 null
        11 null
        12 null

8 rows selected.

SQL> delete from employees where ROWID NOT IN (select min(ROWID) from employees
group by ssn,name);

2 rows deleted.

SQL> select * from employees;

       SSN NAME
---------- ----------
         1 helen
         2 helen
         2 peter
        10 sally
        11 null
        12 null

6 rows selected.

6

请注意,ROWID在数据库导入和导出周期中不会持久存在。您绝不能将ROWID存储在表中作为关键值。


4

ROWID由以下组成(但不一定按照这个顺序,尽管我记得ROWNUM部分是ROWID的最后一部分):

  • OBJID 对象的唯一标识符。
  • FILENO 表空间中数据文件的相对编号。
  • BLOCKNO 在文件头之后的数据文件中的相对块编号。
  • ROWNUM 块内的相对行号。

您可以使用ROWIDTOCHAR() SQL函数轻松将ROWID拆分为其组合字段(OBJID、FILENO、BLOCKNO、ROWNUM),或者使用:

    SQL> select DBMS_ROWID.ROWID_OBJECT(rowid) "OBJECT",
    2         DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) "FILE",
    3         DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) "BLOCK",
    4         DBMS_ROWID.ROWID_ROW_NUMBER(rowid) "ROW"
    5  from dual
    6  /
        OBJECT       FILE      BLOCK        ROW
    ---------- ---------- ---------- ----------
           258          1       2082          0

请注意,字段ROWNUM(或上述查询中的ROW)并非您在SELECT查询中使用的SQL伪列ROWNUM,后者只是结果集中某一行的动态生成行号。
请注意,由于这种实现方式,行、块、扩展和段不能在不破坏ROWID的情况下进行传输,这会使索引失效。
ROWID是访问包含该行的块的最直接路径,并唯一标识该行,因为它编码了唯一的文件、该文件内唯一的块以及该块内唯一的行。
更多信息:
请参阅:有关ROWID格式的DBMS笔记 注意:
如果您稍微了解Oracle结构化数据库文件和块的方式,并了解一些C编程知识,则可以轻松编写一个程序,显示由ROWID给出的块的内容(起始于fileheadersize + BLOCKNO * BLOCK_SIZE的8k或数据库中使用的任何块大小的块。该块包含块头,之后是行目录,对于每行,它都在块中给出了相对偏移量。例如,在行目录中的位置0是块中第0个行的相对偏移量,在行目录中的位置1是第1个行的相对偏移量,等等。行数本身存储在块头的某个位置(请参阅Oracle有关块布局的文档)。
有了一点编程知识并查阅有关Oracle数据库文件和块的文档,您可以看到如何在磁盘上存储行,甚至重构每列存储的行的所有值。每行包含长度和列数的元数据,对于每列,它还指示列的类型以及字节大小,然后是该值。字节大小为0意味着该列数据为空(或:NULL)。

3

ROWID是用于唯一标识表中的行。而 ROWNUM 给出了特定查询结果集中每一行的行号。这两者非常不同,不能互换使用。

此外,还有一个名为 ROW_NUMBER 的更现代化的版本,其行为略有不同。请查看此文章,详细解释了它们之间的差异: http://explainextended.com/2009/05/06/oracle-row_number-vs-rownum/


1

ROWID基本上允许您有两行具有完全相同的数据。虽然,通常您希望您的主键比RowID更有意义,但这只是一种自动确保行之间唯一性的简单方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接