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条记录的原因。
- 首先通过T表的全表扫描得到了侯选集合(不一定就是全表扫描,只是本例是通过全表扫描方式得到侯选集合。如下图)

- 从侯选集合中fetch一条记录,预分配ROWNUM=1,此时mod(1,4)=1,符合FILTER条件(mod(rownum,4)=1),该记录返回,并将ROWNUM=1实际分配给该记录,当前ROWNUM变为2
- 从侯选集合中fetch下一条记录,预分配ROWNUM=2,此时mod(2,4)=2,不符合FILTER条件,该记录被丢弃,当前ROWNUM不变化
- 此后将一直重复步骤3,直至侯选集合被完全遍历。
- 最终只有1条记录被返回。
可以通过一个微调进一步验证上述过程。如果把SQL改为:
select count(*) from t where mod(rownum,4)=2;
会有多少条记录返回呢?
答案是:一条也没有。

结论:
1、凡是涉及使用ROWNUM作为谓词条件的,一定要当心上述陷阱:凡是有可能使ROWNUM不能持续分配的操作、函数,均有可能导致类似现象。
Oracle ROWNUM的陷阱的更多相关文章
- Oracle rownum 分页, 排序
Oracle rownum 分页, 排序 什么是rownum, rownum的生成, rownum相关的符号操作 Rownum是oracle生成结果集时得到的一个伪列, 按照读出行的顺序, 第一条ro ...
- 160628、利用Oracle rownum让表排序字段值连续
利用Oracle rownum让表排序字段值连续 1.需求说明 表(eval_index)中有字段如下: 表字段 描述 说明 ID 主键 GROUP_ID 分组编号 SORT_NUM 排序序号 按照分 ...
- [Oracle] ROWNUM和分页
rownum是oracle的一个伪劣,它的顺序依据从表中获取记录的顺序递增,这里要注意的是:由于记录在表中是无序存放的.因此你无法通过简单的rownum和order by的组合获得相似TOP N的结果 ...
- Oracle rownum
本问参考自Oracle中ROWNUM的使用技巧.纯属读书笔记,用于加深记忆 rownum是oracle中的一种伪列,它会根据返回的记录生成一个序列化的数字,利用rownum,我们可以得到一些原先难以得 ...
- oracle rownum paging issues
rownum是oracle预处理字段,默认标序是1,只有记录集已经满足条件后才会进行后续编号.由于第一条记录rownum默认是1,而你的条件是rownum>=6 对第一条记录比较它的rownum ...
- Oracle ROWNUM用法和分页查询总结(转)
[转载] Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用. Oracle分页查询格式(一):http://yangtingkun.itpub.net/post/468/100278 ...
- Oracle SQL篇(三)Oracle ROWNUM 与TOP N分析
首先我们来看一下ROWNUM: 含义解释: 1.rownum是oracle为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推.这是一个伪列,可以用于限制查询返回的总行数. 2 ...
- ORACLE ROWNUM解析
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp53 [align=middle;" align="le ...
- Oracle ROWNUM用法和分页查询总结
**************************************************************************************************** ...
随机推荐
- python开发总结
1.思维缜密的编程逻辑 2.满足明确的目的需求 3.运用现成的轮子加以改造 4.学会装饰自己的程序 5.化繁为简 6.多用配置文件作为入口 7.注意扩展兼容
- 【Selenium-WebDriver实战篇】java测试使用HttpClient debug日志关闭
在上一篇设置完Tess4J之后,引用jar包之前,我的日志体系一直是只出现info级别的,但是引用之后出现很多httpClient的请求. 于是网上调查了下,可以通过代码实现,就在入口程序增加该部分代 ...
- HBase应用
太多column family的影响 每个 MemoryStore分配到的内存较少,进而导致过多的合并,影响性能 几个column family比较合适呢 推荐是:1-3个 划分column fa ...
- finall语句是在return语句执行前被执行还是执行后被执行?
finally对try...catch的影响和执行时间 一.finally语句不被执行的两种情况 我们在学习抛出异常的时候学习到了finally语句块,这个语句块一般会被执行,但是有两种情况下不被执行 ...
- LeetCode 919. Complete Binary Tree Inserter
原题链接在这里:https://leetcode.com/problems/complete-binary-tree-inserter/ 题目: A complete binary tree is a ...
- 使用jstack命令查看CPU高占用的问题记录
笔记: 1.top命令找出最高占用的进程(command为java) 2.查看高负载进程下的高负载线程:top -Hp [PID] (或 ps -mp PID -o THREAD,tid,time) ...
- php保存canvas导出的base64图片
代码如下: <?php $img='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABxCAYAAABoUdWRAAAAAXNSR0IAr ...
- C++2.0新特性(八)——<Smart Pointer(智能指针)之unique_ptr>
一.概念介绍 unique_ptr它是一种在异常发生时可帮助避免资源泄露的smart pointer,实现了独占式拥有的概念,意味着它可确保一个对象和其他相应资源在同一时间只被一个pointer拥有, ...
- (五)Cisco dhcp snooping实例3-多交换机环境(DHCP服务器和DHCP客户端位于同VLAN)
试验拓扑 环境:dhcp server和dhcp客户端属于同vlan,但是客户端属于不同的交换机,在L2和L3交换机开启dhcp snooping后得出如下结论 L3交换机的配置 ip dhcp po ...
- 移动端 - adb shell常见问题汇总
一.如何执行adb命令? 答:如果没有配置SDK的环境变量的话,那就先用cd命令进入adb所在文件目录(即F:\android-sdk-windows\platform-tools)后,再执行adb命 ...