1. 程式人生 > >Oracle中ROWNUM偽列和ROWID偽列的用法與區別

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 WHERE
a.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);