rowid记录数据的物理位置,通过rowid可以知道数据存放在那个数据文件的第几个块第几行。


---------------------
extended rowid format 
----------------------------------------------------
AAAEoF           AAE             AAAACL    AAA
----------------------------------------------------
data object   relative file      block     row 
number        number             number    number
----------------------
第一部分:数据段id select * from dba_objects 
第二部分:文件的相对编号 dba_data_files
第三部分:块编号
第四部分:行编号,这个块上的第几行
rowid:记录这条数据的物理位置

rowid使用64进制,定义如下:
-----------------------------
A~Z : 0~25
a~z : 26~51
0~9 : 52-61
+   : 62    
/   : 63
-------------------------------


例:AAE转为十进制,方法如下:
A = 0
E = 4

AAE = 0*64^2 + 0*64^1 + 4*64^0 = 4 

转换过程:把AAE解析成64进制的数据,然后每个位数*64的N次方,再相加后的值就是10进制。



转换原理已清楚,下面使用代码来解析rowid信息,不过代码写得太……

--------------------------------------------------------
--AAAY50 AAG   AAAACL AAA
--1,6    7,3   10,6  16,3

--处理rowid
create or replace procedure v_oprowid(v_rowid in varchar2)
as
v_dataid varchar2(6);
v_rfileid varchar2(3);
v_blockid varchar2(6);
v_xingid varchar2(3);
v_all varchar(32);
v_chk number;
v_temp number;
v_temp64 number default 0;
begin
  select substr(v_rowid,1,6),substr(v_rowid,7,3),substr(v_rowid,10,6),
  substr(v_rowid,16,3) into v_dataid,v_rfileid,v_blockid,v_xingid from dual;
  --dbms_output.put_line('objecct_id:'||v_dataid||',rfileid:'
  --||v_rfileid||',blockid:'||v_blockid||',xingid:'||v_xingid);

  for i in 1..6 loop
    v_temp:=ascii(substr(v_dataid,i,1));
    v_chk:= v_temp-65;
    if v_chk>=0 and v_chk <= 25 then
        v_temp64 :=v_temp64+v_chk*power(64,6-i);
    end if;
    if v_chk < 0 and v_chk>=-17 then
        v_temp64 :=v_temp64+(v_chk+69)*power(64,6-i);
    end if;
    
    if v_chk >=32 and v_chk<=57 then
         v_temp64 :=v_temp64+(v_chk-6)*power(64,6-i);
    end if;
    if v_chk=-22 then
         v_temp64 :=v_temp64+62*power(64,6-i);
    end if;
    
     if v_chk=-18 then
         v_temp64 :=v_temp64+63*power(64,6-i);
    end if;    
  end loop;
  dbms_output.put_line('object_data_id:'||v_temp64);
  
  --relative_fno
    
  v_temp64:=0;
   for i in 1..3 loop
    v_temp:=ascii(substr(v_rfileid,i,1));
    v_chk:= v_temp-65;
    if v_chk>=0 and v_chk <= 25 then
        v_temp64 :=v_temp64+v_chk*power(64,3-i);
    end if;
    if v_chk < 0 and v_chk>=-17 then
        v_temp64 :=v_temp64+(v_chk+69)*power(64,3-i);
    end if;
    
    if v_chk >=32 and v_chk<=57 then
         v_temp64 :=v_temp64+(v_chk-6)*power(64,3-i);
    end if;
    if v_chk=-22 then
         v_temp64 :=v_temp64+62*power(64,3-i);
    end if;
    
     if v_chk=-18 then
         v_temp64 :=v_temp64+63*power(64,3-i);
    end if;    
  end loop;
  dbms_output.put_line('relative_fno:'||v_temp64);
   
--
  v_temp64:=0;
  for i in 1..6 loop
    v_temp:=ascii(substr(v_blockid,i,1));
    v_chk:= v_temp-65;
    if v_chk>=0 and v_chk <= 25 then
        v_temp64 :=v_temp64+v_chk*power(64,6-i);
    end if;
    if v_chk < 0 and v_chk>=-17 then
        v_temp64 :=v_temp64+(v_chk+69)*power(64,6-i);
    end if;
    
    if v_chk >=32 and v_chk<=57 then
         v_temp64 :=v_temp64+(v_chk-6)*power(64,6-i);
    end if;
    if v_chk=-22 then
         v_temp64 :=v_temp64+62*power(64,6-i);
    end if;
    
     if v_chk=-18 then
         v_temp64 :=v_temp64+63*power(64,6-i);
    end if;    
  end loop;
  dbms_output.put_line('blockid:'||v_temp64);
  
---
  v_temp64:=0;
   for i in 1..3 loop
    v_temp:=ascii(substr(v_xingid,i,1));
    v_chk:= v_temp-65;
    if v_chk>=0 and v_chk <= 25 then
        v_temp64 :=v_temp64+v_chk*power(64,3-i);
    end if;
    if v_chk < 0 and v_chk>=-17 then
        v_temp64 :=v_temp64+(v_chk+69)*power(64,3-i);
    end if;
    
    if v_chk >=32 and v_chk<=57 then
         v_temp64 :=v_temp64+(v_chk-6)*power(64,3-i);
    end if;
    if v_chk=-22 then
         v_temp64 :=v_temp64+62*power(64,3-i);
    end if;
    
     if v_chk=-18 then
         v_temp64 :=v_temp64+63*power(64,3-i);
    end if;    
  end loop;
  dbms_output.put_line('xingid:'||v_temp64);
  
 
end;
--procedure end
----------------------------------------------------------------




执行方法:

SQL> set serveroutput on
SQL> exec v_oprowid('AAAY50AAGAAAACLAAB')
object_data_id:102004
relative_fno:6
blockid:139
xingid:1

PL/SQL 过程已成功完成。

SQL>






oracle提供dbms_rowid包中的函数可以读取rowid解析成可读信息,语句如下:

select dbms_rowid.rowid_object(rowid),
dbms_rowid.rowid_relative_fno(rowid),
dbms_rowid.rowid_block_number(rowid),
dbms_rowid.rowid_row_number(rowid),rowid from wen.t;