rowid概述
rowid是一個用來唯一標記表中行的偽列。它是物理表中行數據的內部地址,包含兩個地址,其一為指向數據表中包含該行的塊所存放數據文件的地址,另一個是可以直接定位到數據行自身的這一行在數據塊中的地址。
除了在同一聚簇中可能不唯一外,每條記錄的rowid是唯一的。可以理解成rowid就是唯一的。
擴展ROWID
從Oracle 8i開始使用擴展rowid標識行物理地址
擴展rowid使用base64編碼行的物理地址,編碼字符包含A-Z, a-z, 0-9, +,
和/。
擴展rowid由四部分組成:OOOOOOOFFFBBBBBBRRR:
rowid包含如下內容:
①:對象所在的數據文件號
②:對象所在的塊號
③:對象所在行在塊內的位置
④:對象號
其中:
- OOOOOO:數據對象編號(6位顯示)
- FFF:相關數據文件編號(3位顯示)
- BBBBBB:數據塊編號(6位顯示)
- RRR:數據塊中行編號(3位顯示)
Oracle正是根據這些內容找到相應的數據的。
查詢到的rowid示例
SELECT ROWID FROM T_EMP ORDER BY ROWID
ROWID的使用——快速刪除重復的記錄
ROWID是數據的詳細地址,通過rowid,oracle可以快速的定位某行具體的數據的位置。
ROWID可以分為物理rowid和邏輯rowid兩種。普通的表中的rowid是物理rowid,索引組織表(IOT)的rowid是邏輯rowid。
當表中有大量重復數據時,可以使用ROWID快速刪除重復的記錄。
舉例:
--建表tbl
SQL> create table stu(no number,name varchar2(10),sex char(2));
--添加測試記錄
SQL> insert into stu values(1, 'ab',’男’);
SQL> insert into stu values(1, 'bb',’女’);
SQL> insert into stu values(1, 'ab',’男’);
SQL> insert into stu values(1, 'ab',’男’);
SQL>commit;
刪除重復記錄方法很多,列出兩種。
⑴ 通過創建臨時表
可以把數據先導入到一個臨時表中,然后刪除原表的數據,再把數據導回原表,SQL語句如下:
SQL>create table stu_tmp as select distinct* from stu;
SQL>truncate table sut; //清空表記錄
SQL>insert into stu select * from stu_tmp; //將臨時表中的數據添加回原表
這種方法可以實現需求,但是很明顯,對於一個千萬級記錄的表,這種方法很慢,在生產系統中,這會給系統帶來很大的開銷,不可行。
⑵ 利用rowid結合max或min函數
使用rowid快速唯一確定重復行結合max或min函數來實現刪除重復行。
SQL>delete from stu a where rowid not in (select max(b.rowid) from stu b where a.no=b.no and a.name = b.name and a.sex =b.sex); //這里max使用min也可以
或者用下面的語句
SQL>delete from stu a where rowid < (select max(b.rowid) from stu b where a.no=b.no and a.name = b.name and a.sex = b.sex);
//這里如果把max換成min的話,前面的where子句中需要把"<"改為">"
跟上面的方法思路基本是一樣的,不過使用了group by,減少了顯性的比較條件,提高效率。
SQL>delete from stu where rowid not in (select max(rowid) from stu t group by t.no, t.name, t.sex );
思考:若在stu表中唯一確定任意一行數據(1, 'ab',’男’),把sex字段更新為”女”,怎么做?
SQL>update stu set sex=’女’ where rowid=(select min(rowid) from stu where no=1 and name=’ab’ and sex=’男’);
我的理解:當想要得到唯一值的時候就可以考慮使用rowid來進行處理