ROWID (oracle) - 有什么用吗?

发布于 2024-08-29 21:29:35 字数 111 浏览 7 评论 0原文

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

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

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

My understanding is that the ROWID is a unique value for each row in the result returned by a query.

Why do we need this ROWID? There is already the ROWNUM in ORACLE.

Have any one used ROWID in a SQL query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

标点 2024-09-05 21:29:35

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

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

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

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

编辑

给定记录的 ROWID 可以在系统的生命周期内更改,例如通过表重建。此外,如果删除一条记录,则可以为新记录指定该 ROWID。因此,从长远来看,ROWID 不适合用作 UID。但它们足以在事务中使用。

ROWID is the physical location of a row. Consequently it is the fastest way of locating a row, faster even than a primary key lookup. So it can be useful in certain types of transaction where we select some rows, store their ROWIDs and then later on use the ROWIDs in where clauses for DML against those same rows.

The Oracle SELECT ... FOR UPDATE syntax implicitly uses ROWID, when we update the locked row using WHERE CURRENT OF. Also the EXCEPTIONS table (referenced when applying constraints with the EXCEPTIONS INTO clause) has a column ROW_ID. This allows us to quickly identify the rows which are breaking our constraint.

That latter example points to another general usage: when we are writing some generic piece of code and need a mechanism for storing UIDs without concerns regarding data type, composite keys, etc.

ROWNUM on the other hand is a pseudo-column which tags a row in a given result set. It has no permanent significance.

edit

The ROWID for a given record can change over the lifetime of a system, for instance through a table rebuild. Also if one record is deleted a new record could be given that ROWID. Consequently ROWIDs are not suitable for use as UIDs in the long term. But they are good enough for use within a transaction.

蓦然回首 2024-09-05 21:29:35

我现在知道一个例子。

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

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.

I now know an example for this.

suppose you have table with no primary keys. so this table can have duplicate rows. How would you delete duplicate rows but keep exactly one of that kind?

Oracle provides ROWID as a kind of substitute for primary key. You can write a nested query which is of correlated type [(group by all columns in the row and take MIN(ROWID) in each group in inner query, for each group delete the other rows in the group in outerquery)]

Example

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.
被你宠の有点坏 2024-09-05 21:29:35

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

note that ROWID does not persist across a database EXPORT and IMPORT cycle.
you should NEVER store a rowid in your tables as a key value.

半步萧音过轻尘 2024-09-05 21:29:35

ROWID 由以下部分组成(但不一定按该顺序,尽管据我所知,ROWNUM 部分是 ROWID 的最后部分):

  • OBJID
    对象的唯一标识符。
  • 文件号
    表空间中数据文件的相对编号。
  • 块号
    文件头之后的数据文件中的相对块号。
  • 行号
    块内的相对 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)是 ROWNUM 与您在 SELECT 查询中使用的 SQL 伪列 ROWNUM 不同,它只是结果集中动态生成的行号。

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

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

更多信息:

请参阅:有关 ROWID 格式的 DBMS 注释

注意:

如果您对 Oracle 构造数据库文件和块的方式有一点了解,并且了解一些 C 编程,您可以很容易地编写一个程序来显示 ROWID 给出的块的内容(8k 或任何块) size 在数据库中使用,块从 fileheadersize + BLOCKNO * BLOCK_SIZE 开始,该块包含块头,然后(假设表不是集群)rowdir,它为每行提供块内每行的相对偏移量。例如,rowdir 中的位置 0 是块内第 0 行的相对偏移量,rowdir 中的位置 1 是第一行的相对位置,等等。行数本身存储在某处。在块头中(请参阅有关块布局的 orale 文档)

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

A ROWID consists of (but not necessarily in that order, although the ROWNUM part is the last part of ROWID as far as I remember):

  • OBJID
    The unique indentifier of the object.
  • FILENO
    The relative number of the datafile in the tablespace.
  • the BLOCKNO
    The relative block number in the datafile after the fileheader.
  • the ROWNUM
    The relative rownum within the block.

You can easily break down the ROWID into it's composite fields (OBJID, FILENO, BLOCKNO, ROWNUM) by using the ROWIDTOCHAR() SQL-function, or use:

    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

Note that the field ROWNUM (or ROW in the above query) is not the same ROWNUM as the SQL pseudo column ROWNUM you use in SELECT query, which is just the dynamically generated rownumber of the row in the result set.

Note that because of this implementation, rows, blocks, extents and segments are not transportable without breaking the ROWID, which invalidates indexes.

The ROWID is the most direct access path to the block in which the row resides and uniquely indentifies the row, because it encodes the unique file and unique block within that file and unique row within that block.

More information:

See: DBMS notes on ROWID format

Note:

If you have a little understanding of the way oracle structures database files and blocks, and know some C programming, you could quite easily make a program that displays the contents of the block given by ROWID (an 8k, or whatever block size is used in the database, block that starts at fileheadersize + BLOCKNO * BLOCK_SIZE. The block contains the block header and thereafter (assuming the table is not clustered) the rowdir, which for each row gives the relative offset within the block for each row. So for example at position 0 within the rowdir is the relative offset of the 0-th row within the block, at position 1 within the rowdir the relative position of the 1-st row, etc. The number of rows itself is stored somewhere in the block header (See orale documentation on the block layout).

With a little bit of programming knowledge and looking up the documentation on oracle database files an blocks for the exact layout of blocks, you can see how rows are stored on disk, and even reconstruct all the values the row stores for each column. Each row contains metadata for the length of the row and the number of columns, and for each column, an indication for the type of the column and the bytesize and therafter the value. Bytesize 0 means that the column data is empty (or: NULL).

无法言说的痛 2024-09-05 21:29:35

ROWID 唯一标识表中的行。 ROWNUM 为您提供特定查询结果的行号。两者有很大不同,不能互换。

还有 ROW_NUMBER,它是 ROWNUM 的更现代版本,并且行为略有不同。请查看这篇文章,其中解释了其中的差异。

ROWID uniquely identifies a row within a table. ROWNUM gives you the row number of a result for a specific query. The two are very different and are not interchangeable.

Also there is ROW_NUMBER which is a more modern version of ROWNUM, and behaves slightly differently. Check out this article which explains the difference.

提赋 2024-09-05 21:29:35

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

ROWID basically allows you to have two rows with the exact same data. While, you typically want your Primary Key to be a little more meaningful than a RowID, it is just a simple way of automatically ensuring uniqueness between rows.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文