oracle rowid详解

1.rowid的介绍
先对rowid有个感官认识:
SQL> select ROWID from Bruce_test where rownum<2;
ROWID
------------------ ----------
AAABnlAAFAAAAAPAAA

ROWID的格式如下:

数据对象编号        文件编号        块编号           行编号
OOOOOO              FFF             BBBBBB           RRR

我们可以看出,从上面的rowid可以得知:
AAABnl 是数据对象编号
AAF是相关文件编号
AAAAAP是块编号
AAA 是行编号

怎么依据这些编号得到具体的十进制的编码值呢,这是经常遇到的问题。

这里需要明白rowid是基于64位编码的18个字符显示(数据对象编号(6)+文件编号(3)+块编号(6)+行编号(3)=18位),其中
A-Z <==> 0 - 25 (26)
a-z <==> 26 - 51 (26)
0-9 <==> 52 - 61 (10)
+/ <==> 62 - 63 (2)
共64位,明白这个后,就可以计算出10进制的编码值,计算公式如下:
d * (b ^ p)
其中:b就是基数,这里就是64,p就是从右到左,以0开始的位置数
比如:上面的例子文件号AAF,具体的计算应该是:
5*(64^0)=5;
0*(64^1)=0;
0*(64^2)=0;
文件号就是0+0+5=5

刚才提到的是rowid的显示方式:基于64位编码的18个字符显示

其实rowid的存储方式是:10 个字节即80位存储,其中数据对象编号需要32 位,相关文件编号需要10 位,块编号需要22,行编号需要16 位

2.rowid相关的有用的sql

最简单的基于rowid的显示方式得到相应的64位编码对应值的sql:
select rowid ,
substr(rowid,1,6) "OBJECT",
substr(rowid,7,3) "FILE",
substr(rowid,10,6) "BLOCK",
substr(rowid,16,3) "ROW"
from TableName;

SQL> select rowid ,
  2  substr(rowid,1,6) "OBJECT",
  3  substr(rowid,7,3) "FILE",
  4  substr(rowid,10,6) "BLOCK",
  5  substr(rowid,16,3) "ROW"
  6  from dept;

ROWID              OBJECT       FILE   BLOCK        ROW
------------------ ------------ ------ ------------ ------
AAACYAAAEAAAAAKAAA AAACYA       AAE    AAAAAK       AAA
AAACYAAAEAAAAAKAAB AAACYA       AAE    AAAAAK       AAB
AAACYAAAEAAAAAKAAC AAACYA       AAE    AAAAAK       AAC
AAACYAAAEAAAAAKAAD AAACYA       AAE    AAAAAK       AAD
AAACYAAAEAAAAAKAAE AAACYA       AAE    AAAAAK       AAE
AAACYAAAEAAAAAKAAF AAACYA       AAE    AAAAAK       AAF
AAACYAAAEAAAAAKAAG AAACYA       AAE    AAAAAK       AAG

7 rows selected.

通过dbms_rowid这个包,可以直接得到具体的rowid包含的信息(十进制):

select dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowid) block_id ,dbms_rowid.rowid_row_number(rowid) num from bruce_t where rownum<5;
OBJECT_ID    FILE_ID   BLOCK_ID        NUM
---------- ---------- ---------- ----------
      5944          3      25300          0
      5944          3      25300          1
      5944          3      25300          2
      5944          3      25300          3

3.一些使用ROWID的函数

ROWIDTOCHAR(rowid) :将ROWID转换成STRING
CHARTOROWID('rowid_string') :将STRING转换成ROWID
另外,就是自己写的一些函数:(下面的函数是网友eygle提供)
create or replace function get_rowid (l_rowid in varchar2) return varchar2
is
 ls_my_rowid     varchar2(200);        
 rowid_type     number;        
 object_number     number;        
 relative_fno     number;        
 block_number     number;        
 row_number     number;
begin
    dbms_rowid.rowid_info(l_rowid,rowid_type,object_number,relative_fno, block_number, row_number);        
    ls_my_rowid := 'Object# is      :'||to_char(object_number)||chr(10)||
        'Relative_fno is :'||to_char(relative_fno)||chr(10)||
        'Block number is :'||to_char(block_number)||chr(10)||
        'Row number is   :'||to_char(row_number);
    return ls_my_rowid ;
end;       
/

应用上面的函数如下:
SQL> select get_rowid(rowid), name from bruce_t;
GET_ROWID(ROWID)                                                                 NAME
-------------------------------------------------------------------------------- --------------------------------
Object# is      :5944                                                      BruceLau
Relative_fno is :3                                                             
Block number is :25300                                                         
Row number is   :0                                                             
Object# is      :5944                                                     MabelTang
Relative_fno is :3                                                             
Block number is :25300                                                         
Row number is   :1

ROWID:ROWID为表行的唯一标识,是一个伪列,可以用在SELECT中,但不可以用INSERT, UPDATE来修改该值。

注意:ROWID的表指:table,cluster table, partition table, subpartition table, index, index partitions and subpartitions(注意:不包含index-organized tables).
每个表Oracle都存在一个伪列ROWID,这个伪列可以用SELECT查看,但是不可以用INSERT, UPDATE来修改。
你也不可以用DELETE来删除ROWID列,Oracle使用ROWID列来建立内部索引。
你可以引用ROWID的值,但ROWID并不存放在数据库中,你可以创建一个表包含ROWID数据类型,但Oracle不保证该值是合法的rowid。用户必须确保该rowid值是真实合法的。

再次强调一次,rowid伪列不存储在数据库中,它不是数据库数据,这是从database及table的逻辑结构来说的,事实上,在物理结构上,每行由一个或多个row pieces组成,每个row piece的头部包含了这个piece的address,即rowid.从这个意义上来说,rowid还是占了磁盘空间的.

我们在创建表时,可以为列指定为rowid数据类型,但oracle并不保证列中的数据是合法的rowid值,必须由应用程序来保证,另外,类型为rowid的列需要6 bytes存储数据

只要行存在,它的物理地址rowid就不会变化,除非export/import,根据rowid可以直接定位到block去fetch数据

要注意rowid的地址固定的特点,在一个block的某一行被delete并commit后,它占据的address可以被其它事务新insert的行重用.

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

历史五千年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值