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;
转载于:https://blog.51cto.com/hxw168/1556624