昨天小定同学突然问我一个分页问题,分页干嘛要这样分成两层查询,而不是对行号一层过滤就可以了呢?分页语句的语法类似是这样的:
SELECT * FROM
(SELECT ROWNUM AS RN, T.* FROM PA_LD_BASIC_DATA T WHERE ROWNUM <= 200)
WHERE RN > 100;
小定同学的想法是为什么不能是如下这种写法呢?
SELECT ROWNUM, T.* FROM PA_LD_BASIC_DATA T
WHERE ROWNUM <= 200 AND
ROWNUM > 100;
想来Oracle的伪列经常被使用,但可能有同学对它到底是怎么用的,具体的用法不是很清楚,结合Oracle官方文档,在这里写一点总结。
查询官方文档如下:

rownum是一种分析功能,在数据集查询完成后,在任何聚合和排序操作之前为要应用它的每一行(分区中的每一行或查询返回的每一行)分配一个唯一的编号,且总是从1开始。
而且文档中说明,任何大于rownum的值的筛选条件结果总是为false,不会查询出任何数据。例如当条件为rownum > 10时,查询完成,为数据集第一行数据的rownum分配为1,不满足条件,然后数据集的第二行的rownum现在分配为1,以此下去,rownum > 10的条件将永远不会满足,所以没有任何数据被返回。
最后看我们的分页查询,直接使用rownum > 100也将不会返回任何数据,所以分页的时候不能同时对rownum采用between...and这种筛选,需要采用子查询构建数据集,让rownum成为数据集的列,然后对该列进行过滤。