我的理解是,ROWID是查询结果中每一行的唯一值。
为什么我们需要ROWID?ORACLE已经有ROWNUM了。
有人在SQL查询中使用过ROWID吗?
ROWID是一行的物理位置,因此它是定位行的最快方法,甚至比主键查找更快。因此,在某些事务类型中,选取某些行、存储其ROWIDs,然后稍后在对这些相同行进行DML时使用ROWIDs的where子句非常有用。
当我们使用WHERE CURRENT OF更新被锁定的行时,Oracle SELECT ... FOR UPDATE语法隐式地使用ROWID。同时,应用EXCEPTIONS INTO子句约束时引用EXCEPTIONS表(具有ROW_ID列)。这使我们能够快速识别违反约束的行。
后面那个例子指向另一种通用用途:当我们编写一些通用代码并需要一种机制来存储UIDs而不必考虑数据类型、复合键等。
另一方面,ROWNUM是一个伪列,标记给定结果集中的一行。它没有永久意义。
编辑
给定记录的ROWID在系统运行期间可能会发生变化,例如通过表重建。此外,如果删除一个记录,新记录可能会获得该ROWID。因此,ROWID不适合长期用作UID。但是在事务内部使用它们足够好。
我现在有一个例子。
假设你有一张没有主键的表,因此该表可能会有重复的行。那么如何删除重复的行但保留其中一条?
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.
请注意,ROWID在数据库导入和导出周期中不会持久存在。您绝不能将ROWID存储在表中作为关键值。
ROWID由以下组成(但不一定按照这个顺序,尽管我记得ROWNUM部分是ROWID的最后一部分):
您可以使用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
ROWID是用于唯一标识表中的行。而 ROWNUM 给出了特定查询结果集中每一行的行号。这两者非常不同,不能互换使用。
此外,还有一个名为 ROW_NUMBER 的更现代化的版本,其行为略有不同。请查看此文章,详细解释了它们之间的差异: http://explainextended.com/2009/05/06/oracle-row_number-vs-rownum/
ROWID基本上允许您有两行具有完全相同的数据。虽然,通常您希望您的主键比RowID更有意义,但这只是一种自动确保行之间唯一性的简单方法。