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;
本文出自 “尽管错,让我错到死!” 博客,请务必保留此出处http://hxw168.blog.51cto.com/8718136/1556624