暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle ROWNUM虫子

askTom 2017-05-19
306

问题描述

嗨,
我读了下面的问题
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:948366252775
在最新的跟进中,读者像这样发布
(
5 years later...

select * from X where rownum in (select 1 from dual)

still returns all the rows. 
)

--Query 1
select * from employees where rownum in (select 1 from dual)

所以我尝试了该查询它返回所有行。但是从dual中选择1只返回具有1个值的一行。

我也试过这样

--Query 2
select * from employees where rownum in (1,2,3); --Returns 3 rows

--Query 3
select * from employees where rownum in (1,2,3,5); --Returns 3 rows

--Query 4
select * from employees where rownum in (1,2,3,4); --Returns 4 rows


create table t2 (sno number);
inserted into t2 from 1-4 (refer live sql for all above scripts)

--Query 5
select * from employees where rownum in (select sno from t2);  --Returns 0 rows

所以我的问题是

1.为什么query 1从employees表中返回所有行?
2.查询2返回3行,查询3也3行,但查询4返回4为什么它返回那样?
3.查询5没有返回任何行,子查询alos返回1,2,3,4
4.查询如何与IN子句一起工作

专家解答

Tom对查询中的rownum如何工作以及为什么在您提到的线程中这是错误的原因有很好的解释。但这里有一个简短的回顾:

这个查询的计划看起来像这样:

SQL> set autotrace trace exp
SQL> select * from hr.employees where rownum in (select 1 from dual);

Execution Plan
----------------------------------------------------------
Plan hash value: 3351781302

---------------------------------------------------------------------------------
| Id  | Operation           | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |           |   107 |  7383 |     5   (0)| 00:00:01 |
|   1 |  COUNT              |           |       |       |            |          |
|*  2 |   FILTER            |           |       |       |            |          |
|   3 |    TABLE ACCESS FULL| EMPLOYEES |   107 |  7383 |     3   (0)| 00:00:01 |
|   4 |    FAST DUAL        |           |     1 |       |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter( EXISTS (SELECT 0 FROM "SYS"."DUAL" "DUAL" WHERE ROWNUM=1))


请注意,IN已变为:

EXISTS (SELECT 0 FROM "SYS"."DUAL" "DUAL" WHERE ROWNUM=1)


每一行都是如此。但这也是错误的!这与原始查询的含义不同。所以你得到了所有的行,而不是只有一行。

具有以下功能的查询:

col in (1,2,3)


相当于:

col = 1 or col = 2 or col = 3


所以当你有:

rownum in (1,2,3,5)


你真正拥有的是:

rownum = 1 or rownum = 2 or rownum = 3 or rownum = 5


由于相同的原因,这仅返回三行

rownum = 2


什么也不返回: 你永远不会有rownum = 4的行。所以rownum = 5总是假的。所以你只有三排。鉴于

rownum in (1,2,3,4)


会有一行,其中rownum = 4,所以你得到4回来。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论