Oracle 数据类型及存储方式(六)
第六部分 ROWID
ROWID 就是数据库中一行的地址,用于记录数据存储的一些属性,包括:记录存储所在的数据文件(file#),所属的数据库对象(obj#),所在的数据块号(block_no#),以及在表中的行号。这些属性就构成了Oracle 的ROWID.
我们需要注意的是在数据表中并没有一列来专门记录ROWID。
另外还有一个UROWID,它用于表,是行主键的一个表示,基于主键生成.一般是索引组织表在使用。索引组织表是没有ROWID的。
不管是ROWID还是UROWID,数据表都没有专门的一列来记录。
我们把这两种类型称为伪列。
SQL> create table test_rowid (id number(38));
Table created
SQL> insert into test_rowid values(1);
1 row inserted
SQL> select rowid, id from test_rowid;
ROWID ID
------------------ ---------------------------------------
AAAKsAAAEAAAAC+AAA 1
因为ROWID可以唯一的标识一条记录,所以索引中存储了ROWID值,通过索引访问记录,其实也就是通过从索引获得ROWID,再根据ROWID定位数据表中的记录。
但是当对表进行分区移动之后,索引就需要重建,因为存储位置已经发生了变化,索引中的ROWID已经不能再定位到新的数据了。
ORACLE 的ROWID一直在不断变化。
在ORACLE 6中,ROWID使用6bit来表示文件号。
在ORACLE 8,ROWID的组成是FFFF.BBBBBBBB.RRRR。占用6个字节。
10bit 的file#,22bit的block#,16bit的row #
在ORACLE 9中,Oracle 为ROWID引入了数据对象号的概念dataobj#.
现在ROWID格式变为OOOOOO.FFF.BBBBBB.RRR。最新的ROWID采用Base64编码,一共有18位,代表80位二进制数,其中:O为数据对象号,F是文件号,B是块号,R是行号
32 bit dataobj#+10bit rfile#,+22 bit block# +16bit row#
在以前ROWID是保持不变的,但现在ROWID是会发生改变的。如:
把一行从一个分区移到另一个分区
使用闪回表(flashback table)命令将一个数据表恢复到以前的某个时间点
对分区进行操作,如:移动,分解和合并
对段进行收缩
这些操作都会使ROWID发生变化,所以我们不应该把ROWID来作为唯一标识。而是使用一个单独的列为主键用来作数据行的唯一标识。另外主键约束可以实现引用完整性。而ROWID是无法做到的。
笔者曾经使用ROWID排序来实现按数据的写入顺序来显示数据。这在大多数情况下是可以做的,但是如果以后因为维护数据库,对分区进行操作后,这样做是不可行的。
所以应该使用单独的列来记录数据的写入顺序。
ROWID类型的主要用途是与数据库进行交互时,可以快速的指向某一行。比如使用ROWID更新某一行等。可以不通过索引而快速的找到某行记录。并且可以很快的进行行数据的验证。