做過Oracle分頁的人都知道由於Oracle中沒有像MySql中limit函數以及SQLServer中的top關鍵字等,所以只能通過僞列的方式去滿足分頁功能,在此,不談分頁方法,只從根本上去介紹這兩個僞列的用法與原理
rownum和rowid都是僞列,但是兩者的根本是不同的
- rownum是根據sql查詢出的結果給每行分配一個邏輯編號,所以你的sql不同也就會導致最終rownum不同
rowid是物理結構上的,在每條記錄insert到數據庫中時,都會有一個唯一的物理記錄 (不會變)
下面以scott用戶的emp表爲例.
一、ROWNUM僞列
ROWNUM僞列是Oracle首先進行查詢獲取到結果集之後在加上去的一個僞列,這個僞列對符合條件的結果添加一個從1開始的序列號,先看一個例子:
SELECT ROWNUM,empno,ename,job FROM emp WHERE deptno = 30;
結果如下:
可以看到確實添加了一列從1開始的序列號,那麼有了這個僞列,就可以完成好多提取數據的工作,比如提取emp表中前5條數據,SQL如下:
SELECT ROWNUM,empno,ename,job FROM emp WHERE ROWNUM < 6;
ROWNUM是動態的,也就是必須先有查詢到的結果集,然後再給這個結果集加上一個列,比如給結果集中的第一條數據的ROWNUM的值爲1,依次類推,如果此時這樣寫:
SELECT ROWNUM,empno,ename,job FROM emp WHERE ROWNUM > 5 AND ROWNUM <= 10;
當生成結果集時,Oracle首先會產生一條ROWNUM爲1的記錄,顯然不符合條件,那麼同樣會繼續產生第二條數據,同樣標識ROWNUM爲1,該條記錄同樣繼續被過濾掉,後續生成的ROWNUM依然爲1,因此上述查詢語句不會有任何查詢結果,所以如果想要使上述結果有滿足條件的結果集,必須使用子查詢(把rownum查出來後放在一個虛表中作爲這個虛表的字段再根據條件查詢),代碼如下:
SELECT * FROM (SELECT ROWNUM nums,emp.* FROM emp) WHERE nums > 5 AND nums <= 10;
子查詢部分固定表裏面數據的記錄編號,外層查詢過濾子查詢裏面固定的記錄編號就可以實現Oracle分頁!
二、ROWID僞列
同ROWNUM僞列不同的是,它是物理存在的,ROWID是一種數據類型,它使用基於64bit編碼的18個字符來唯一標識一條記錄物理位置的一個ID,類似於Java中一個對象的哈希碼,都是爲了唯一標識對應對象的物理位置,需要注意的是ROWID雖然可以在表中進行查詢,但是其值並未存儲在表中(既然是僞列,就說明表中並不會物理存儲ROWID的值),所以不支持增刪改操作,下面看個例子:
SELECT ROWNUM,ROWID,empno,ename,job FROM emp WHERE ROWNUM <= 5;
結果如下:
可以看到ROWID確實由18個字符組成,組成結構如下:
數據對象編號 | 文件編號 | 塊編號 | 行編號 |
OOOOOO | FFF | BBBBBB | RRR |
得到一個如下的數據庫表
CREATE TABLE dept_bak AS SELECT * FROM dept; INSERT INTO dept_bak SELECT * FROM dept;
很明顯,數據有重複的,當然你也可以用一個很原始的方法,就是將有重複記錄的表中的數據導到另外一張表中,最後再倒回去。
SQL>create table emp_tmp as select distinct* from emp;
SQL>truncate table emp; //清空表記錄
SQL>insert into empselect * from emp_tmp;//將臨時表中的數據添加回原表
但是要是emp的表數據是百萬級或是更大的千萬級的,那這樣的方法顯然是不明智的,因此我們可以根據rowid來處理,rowid具有唯一性,查詢時效率是很高的,那麼就可以利用這個特性去重,簡單示例代碼如下:
DELETE FROM dept_bak
WHERE ROWID NOT IN(SELECT MIN(ROWID)
FROM dept_bak GROUP BY DEPTNO);
再例如,學生表中的姓名會有重複的情況,但是學生的學號是不會重複的,如果我們要刪除學生表中姓名重複只留學號最大的學生的記錄,怎麼辦呢?可以參考如下做法:
DELETE FROM stu a
WHERE ROWID NOT IN (SELECT MAX(ROWID)
FROM stu b
WHERE a.name = b.name
AND a.stno < b.stno);
除了上述之外還有好多作用,詳情參照Oracle官方文檔!,在此不多做敘述!