这是因为rownum 的特殊性。这是一个pseudo-column,应用于查询返回的结果集。 (这就是为什么WHERE ROWNUM > 1 总是假的。)
在这种情况下,使用 ROWNUM 会导致查询在 WHERE 子句返回 false 时停止。所以这不会返回任何行(因为 0 只为偶数行返回):
select * from employee a
where 0 = mod(rownum,2);
您的第二种方法有一个子查询,它不在 WHERE 子句中使用 ROWNUM,因此允许返回整个表以在外部查询中进行评估。
任何允许在不评估 ROWNUM 的情况下实现整个结果集的方法都可以使用。这也会产生你想要的结果:
select * from
(select a.*, rownum as rn from employee a)
where mod(rn,2) = 1
/
正如@DavidAldridge 在他的评论中指出的那样,如果没有 ORDER BY 子句,结果集基本上是随机的。 ROWNUM 不能与 ORDER BY 配合使用,因此要保证排序,请改用分析函数 ROW_NUMBER()。
select * from
(select a.*
, row_number() over (order by a.emp_id) as rn
from employee a)
where mod(rn,2) = 0
/
" 下面的查询如何只从表中获取前两条记录。"
通过COUNT STOPKEY 操作的奇迹。查询知道需要多少行;它返回行(并分配 ROWNUM 的值),直到达到该限制。
我们可以在解释计划中看到这一点。没有过滤器:
SQL> explain plan for
2 select * from emp;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 111 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
12 rows selected.
SQL>
这是where rownum <= 2 的计划。注意所选行的不同:
SQL> explain plan for
2 select * from emp
3 where rownum <= 2;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1973284518
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 3 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=2)
Note
-----
- dynamic sampling used for this statement (level=2)
18 rows selected.
SQL>