Oracle中ROWNUM偽列和ROWID偽列的用法與區別
做過Oracle分頁的人都知道由於Oracle中沒有像MySql中limit函式以及SQLServer中的top關鍵字等,所以只能通過偽列的方式去滿足分頁功能,在此,不談分頁方法,只從根本上去介紹這兩個偽列的用法與原理,同樣還是以scott使用者的emp表為例;一、ROWNUM偽列ROWNUM 是Oracle進行查詢獲取到結果集之後,再加上去的一個偽列(獲取一條記錄加一個rownum),這個偽列對符合條件的結果新增一個從1開始的序列號,先看一個例子:
select rownum,empno,ename,job FROM EMP WHERE ROWNUM < 8;
結果如下:ROWNUM是動態的,也就是必須先有查詢到的結果集,然後再給這個結果集加上一個列。 例如:第一條記錄的ROWNUM的值為1 ,第二條是2,以此類推。 如果此時這樣寫:
SELECT ENAME,ROWNUM FROM EMP WHERE ROWNUM > 5 AND ROWNUM <= 10; --查詢結果為空集
當生成結果集時,Oracle首先會產生一條ROWNUM為1的記錄,顯然不符合條件,那麼同樣會繼續產生第二條記錄,同樣標識ROWNUM為1,該條記錄同樣繼續被過濾掉,後續生成的ROWNUM依然為1,因此上述查詢語句不會有任何查詢結果, 導致最後sql產生的結果集時空集。 所以如果想要使上述結果有滿足條件的結果集,必須使用子查詢,程式碼如下:
SELECT * FROM (SELECT ROWNUM rn, a.* FROM emp a) a WHEREa.rn > 5 AND a.rn <= 10;
如果需要查詢到結果,需要使用子查詢:
SELECT rownum,a.* FROM (SELECT ROWNUM rn,a.* FROM EMPLOYEES a WHERE rownum <= 20) a WHERE a.rn > 5 ;
--注意: 1.rownum只能用< 或者<=
2. <或者<=經常放在子查詢裡面二、ROWID偽列同ROWNUM偽列不同的是,ROWID是物理存在的,是實際存在的一個列,ROWID是一種資料型別,它使用基於64位編碼的18個字元來唯一標識一條記錄物理位置的一個ID,類似於Java中一個物件的雜湊碼,都是為了唯一標識對應物件的物理位置,需要注意的是ROWID雖然可以在表中進行查詢,但是其值並未儲存在表中,所以不支援增刪改操作,下面看個例子:
SELECT ROWNUM,ROWID,empno,ename,job FROM emp WHERE ROWNUM <= 5;
可以看到ROWID確實由18個字元組成,組成結構如下:
資料物件編號 | 檔案編號 | 塊編號 | 行編號 |
OOOOOO | FFF | BBBBBB | RRR |
至於ROWID的作用,由於ROWID用來唯一標識表中資料的唯一性,所以可以利用這個特性去除重複,舉個例子,首先執行下述兩行程式碼:
CREATE TABLE dept_bak AS SELECT * FROM dept; INSERT INTO dept_bak SELECT * FROM dept;
得到一個如下的資料庫表 很明顯,資料有重複的,但是ROWID肯定不會重複的,那麼就可以利用這個特性去重,簡單示例程式碼如下:
DELETE FROM dept_bak WHERE ROWID NOT IN( SELECT MIN(ROWID) FROM dept_bak GROUP BY DEPTNO);