rownum和rowid,row_number一點應用

dotaddjj發表於2011-10-14

很早之前就涉及到刪除重複資料,下面的兩個刪除重複資料方法是自己經常用的,置於用一個新表來保留distinct *然後刪除 rename等方法就不提了,因為生產庫是不允許讓表段invaid的。

首先來張測試表吧

Create table student(name varchar2(10),sc number)

然後insert一系列資料。

Select * from student

Name sc

3dd 56

adf 45

fda 80

ffd 78

dss 95

cfe 74

gds 92

gf 99

ddd 99

adf 45

asdf 55

3dd 56

一般生產庫的表段是有主鍵約束的,但是也不排除有些介面表存在大量重複資料,此時需要alter table tablename add primary key(no),但是add主鍵時會檢索我們內部的資料是否存在重複值,此時就需要刪除重複資料,當然生產庫的表的欄位肯定更復雜,但是其實不影響實際的效果。

利用虛列rowid來實現表中資料的刪除

Delete from student where rowid not in select max(rowid) from student group by

Id;

Or

Delete from student a where rowid not in select max(rowid) from student b where a.no=b.no

利用rowid比較方便,效率對一般的資料量都還是不錯的

利用分析函式和虛列rowid刪除重複資料

Delete from student where rowid in

(Select rowid from

Select rowidrow_number()overpartition by no order by nocn from studentb

Where cn>1)

前面的blog提到了oracle的幾個分析函式,主要是針對表段中的欄位先group by分組然後排名,然後保留每個分組排名的第一個即可達到刪除重複資料的solution,而且在執行時間上分析函式明顯優於利用rowid分組的方法。

分頁查詢:

很早之前接觸的一個查詢是查詢出表中的第20行到第50行,剛開始總是想用什麼什麼函式來解決,其實有了一定的開發編寫經驗的人一看就知道是個分頁查詢而已。

Select * from

(select.a.* ,rownum cn from student a where rownum<=51b

where b.cn>=19

其實也是利用rowid虛列資料建成一個含有rowid的實值cn然後巢狀即可。

Select * from

(select.a.* ,rownum cn from student a b

where b.cn between 19 and 51

如果用這個寫法做分頁查詢了,大家可以分別檢視一下他們的執行計劃,其中第一種的執行計劃中有count stopkey這個主要表示在rownum時出現,當達到指定行數時oracle就停止查詢,大多數情況下count stopkey 都明顯高於第二個count的效率,第一個掃描明顯掃需要的邏輯讀少,因為內部的第一個查詢只到rownum<=51就停止了。

學習oracle大半年了,還是覺得自己sql上面的很薄弱,平常也寫的比較少,sql功能不是一個查詢就算完事了,還要考慮到sql的執行計劃 最佳化器 效能上做深入瞭解,但是如果真的要理解這些跟資料查詢在sga和資料檔案如何實現,然後設計到buffer cache中的管理lru列表和dirty列表如何來管理buffer cache的快取,然後sql的解析和執行中又有硬解析 軟解析,然後執行計劃中又有關於索引 cluster等的具體效能上得東西,還往下面可以一直延續下去,估計寫一天也不一定能寫完!

奮鬥吧,為oracle而狂野。

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25362835/viewspace-1055687/,如需轉載,請註明出處,否則將追究法律責任。

相關文章