时间:2021-07-01 10:21:17 帮助过:14人阅读
我们通过一个实验来说明一下。
创建一个具有百万条记录的表:
使用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不能持续分配的操作、函数,均有可能导致类似现象。
Oracle ROWNUM的陷阱
标签:客户 9.png 需要 技术 过滤 进一步 记录 重复 feed