作者:劉穎博
時間:2004-6-12
mail:liuyingbo@126.com,請指正
轉載請注明出處及作者
本文討論的是關于oracle從8i開始引進object的概念后的rowid,即擴展(extended)的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 位,由此,我們可以得出:
32bit的object number,每個數據庫最多有4G個對象
10bit的file number,每個對象最多有1022個文件(2個文件預留)
22bit的block number,每個文件最多有4M個BLOCK
16bit的row number,每個BLOCK最多有64K個ROWS
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;
OWID????????????? OBJECT?????? FILE?? BLOCK??????? ROW
------------------ ------------ ------ ------------ ------
AAABc4AADAAAGLUAAA AAABc4?????? AAD??? AAAGLU?????? AAA
AAABc4AADAAAGLUAAB AAABc4?????? AAD??? AAAGLU?????? AAB
AAABc4AADAAAGLUAAC AAABc4?????? AAD??? AAAGLU?????? AAC
AAABc4AADAAAGLUAAD AAABc4?????? AAD??? AAAGLU?????? AAD
AAABc4AADAAAGLUAAE AAABc4?????? AAD??? AAAGLU?????? AAE
通過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
一些使用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???
?