ROWID(oracle) - 任何用途吗?

时间:2010-04-23 20:25:44

标签: database oracle rowid

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

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

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

6 个答案:

答案 0 :(得分:43)

ROWID是行的物理位置。因此,它是定位行的最快方法,甚至比主键查找更快。所以它在某些类型的事务中很有用,我们选择一些行,存储它们的ROWID,然后在where子句中使用DOW对这些相同的行进行DML。

当我们使用WHERE CURRENT OF更新锁定的行时,Oracle SELECT ... FOR UPDATE语法隐式使用ROWID。此外,EXCEPTIONS表(在使用EXCEPTIONS INTO子句应用约束时引用)具有列ROW_ID。这允许我们快速识别破坏我们约束的行。

后一个例子指出另一个一般用法:当我们编写一些通用代码时,需要一种存储UID的机制,而不用担心数据类型,复合键等。

另一方面,

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

修改

给定记录的ROWID可以在系统的生命周期内更改,例如通过表重建。此外,如果删除一个记录,则可以给出ROWID的新记录。因此,ROWID不适合长期用作UID。但它们足以在交易中使用。

答案 1 :(得分:12)

我现在知道一个例子。

假设您的表没有主键。所以这个表可以有重复的行。你会如何删除重复的行,但保持其中一种?

Oracle提供ROWID作为主键的替代品。您可以编写一个相关类型的嵌套查询[(按行中所有列分组,并在内部查询中的每个组中取MIN(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.

答案 2 :(得分:6)

请注意,ROWID不会在数据库EXPORT和IMPORT周期中持续存在。 你不应该在你的表中存储一个rowid作为键值。

答案 3 :(得分:3)

ROWID唯一标识表中的行。 ROWNUM为您提供特定查询的结果的行号。这两者非常不同,不可互换。

还有ROW_NUMBER是ROWNUM的更现代版本,行为略有不同。查看this article,它解释了差异。

答案 4 :(得分:3)

ROWID由(但不一定按此顺序排列,尽管ROWNUM部分是我记得的ROWID的最后一部分):

  • OBJID 对象的唯一标识符。
  • FILENO 表空间中数据文件的相对编号。
  • BLOCKNO fileheader之后的数据文件中的相对块编号。
  • ROWNUM 街区内的相对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相同的ROWNUM,这只是动态生成的行的rownumber在结果集中。

请注意,由于此实现,行,块,范围和段在不破坏ROWID的情况下是不可传输的,这会使索引无效。

ROWID是行所在块的最直接访问路径,并且唯一地标识该行,因为它编码该文件中的唯一文件和唯一块以及该块中的唯一行。

更多信息:

请参阅:DBMS notes on ROWID format

注意:

如果你对oracle构造数据库文件和块的方式有一点了解,并且知道一些C编程,你可以很容易地创建一个显示ROWID给出的块内容的程序(一个8k,或者任何块大小)在数据库中使用,从fileheadersize + BLOCKNO * BLOCK_SIZE开始的块。该块包含块头,然后(假设表没有聚集)rowdir,每行为每行给出块内的相对偏移量。因此,例如在rowdir内的位置0处是块内第0行的相对偏移,在rowdir内的位置1处,第1行的相对位置等。行数本身存储在某处块头(参见块布局的orale文档)。

通过一些编程知识并在oracle数据库文件上查找文档块的确切布局,您可以看到行如何存储在磁盘上,甚至可以重建行为每个列存储的所有值。每行包含行长度和列数的元数据,对于每列,包含列类型和字节大小以及值后的指示。 Bytesize 0表示列数据为空(或:NULL)。

答案 5 :(得分:0)

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