Oracle ROWNUM的陷阱
先拋出一個問題:
?
我有一張表T,現在我想對表中1/4的記錄作UPDATE操作,我的SQL如下:
Update t set col1='123' where mod(rownum,4)=1
我能夠得到想要的結果嗎?
?
答案是:不能。
我們通過一個實驗來說明一下。
?
創建一個具有百萬條記錄的表:
?
使用mod(rownum,4)=1作謂詞,計劃更新全表1/4的記錄
這張表有百萬條記錄,但該SQL操作feedback的結果竟然是"1 row updated",只有1條記錄被更新。開什么玩笑?
?
UPDATE不行,那我換成查詢怎么樣呢?
仍然只有1條被查詢到。那到底是什么原因導致了這個結果呢?為什么不是預期的1/4的記錄呢?
?
這與ROWNUM偽列的實現機制有關。來看看Oracle官方是如何解釋它的:
ROWNUM是指從表或集合中返回某條記錄的順序值,它只對最終返回的記錄進行分配,未返回的記錄不予分配(返回即表示將結果呈現給客戶端)
?
這句話實際上仍然沒有把它說清楚。下面是我自己的理解:類似于rownum<10或mod(rownum,4)=1這樣的謂詞是屬于FILTER(過濾型)謂詞,這種謂詞需要對侯選集合(例如全表掃描后的侯選集合)進行過濾得到最終結果。在進行過濾操作時,每fetch一條記錄,根據當前的返回順序值預分配ROWNUM,當這條記錄通過FILTER過濾并返回給客戶端,該ROWNUM才實際分配給該條記錄,并使當前返回值+1;如果這條記錄未能通過過濾條件,該記錄被丟棄,當前的返回順序值不變化。
?
現在,我們用上面這段描述來說明上述案例僅返回1條記錄的原因。
?
可以通過一個微調進一步驗證上述過程。如果把SQL改為:
select count(*) from t where mod(rownum,4)=2;
會有多少條記錄返回呢?
?
答案是:一條也沒有。
?
結論:
1、凡是涉及使用ROWNUM作為謂詞條件的,一定要當心上述陷阱:凡是有可能使ROWNUM不能持續分配的操作、函數,均有可能導致類似現象。
轉載于:https://www.cnblogs.com/6yuhang/p/8253007.html
總結
以上是生活随笔為你收集整理的Oracle ROWNUM的陷阱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义View控件(2—手写实例代码)
- 下一篇: 自己动手,实现一种类似ListT的数据结