ORACLE分页查询SQL语法(附效率总结)

本文介绍了五种不同的SQL分页查询方法,包括无ORDERBY排序和有ORDERBY排序的写法,并对比了它们的性能差异。通过实际测试,文章推荐使用特定的方法来提高查询效率,尤其是在处理大量数据时。
--1:无ORDER BY排序的写法。(效率最高)
--(经过测试,此方法成本最低,只嵌套一层,速度最快!即使查询的数据量再大,也几乎不受影响,速度依然!)
SELECT * 
FROM (Select ROWNUM AS ROWNO, T.* 
               
from k_task T 
                
where Flight_date between to_date('20060501''yyyymmdd'
                                                        
and to_date('20060731''yyyymmdd'
                 
AND ROWNUM <= 20) TABLE_ALIAS 
WHERE TABLE_ALIAS.ROWNO >= 10


--2:有ORDER BY排序的写法。(效率最高)
--(经过测试,此方法随着查询范围的扩大,速度也会越来越慢哦!)
SELECT * 
  
FROM (SELECT TT.*, ROWNUM AS ROWNO 
               
FROM (Select t.* 
                           
from k_task T 
                           
where flight_date between to_date('20060501''yyyymmdd'
                                                                 
and to_date('20060531''yyyymmdd'
                           
ORDER BY FACT_UP_TIME, flight_no) TT 
               
WHERE ROWNUM <= 20) TABLE_ALIAS 
where TABLE_ALIAS.ROWNO >= 10


--3:无ORDER BY排序的写法。(建议使用方法1代替)
--(此方法随着查询数据量的扩张,速度会越来越慢哦!)
SELECT * 
  
FROM (Select ROWNUM AS ROWNO, T.* 
                
from k_task T 
                
where Flight_date between to_date('20060501''yyyymmdd'
                                                         
and to_date('20060731''yyyymmdd')
               ) TABLE_ALIAS 
WHERE TABLE_ALIAS.ROWNO <= 20 AND TABLE_ALIAS.ROWNO >= 10
--TABLE_ALIAS.ROWNO  between 10 and 100; 


--4:有ORDER BY排序的写法.(建议使用方法2代替)
--(此方法随着查询范围的扩大,速度会越来越慢哦!)
SELECT * 
  
FROM (SELECT TT.*, ROWNUM AS ROWNO 
                  
FROM (Select * 
                                  
from k_task T 
                                  
where flight_date between to_date('20060501''yyyymmdd'
                                                                         
and to_date('20060531''yyyymmdd'
                                  
ORDER BY FACT_UP_TIME, flight_no) TT
              ) TABLE_ALIAS 
where TABLE_ALIAS.rowno BETWEEN 10 AND 20


--5另类语法。(有ORDER BY写法)
--(语法风格与传统的SQL语法不同,不方便阅读与理解,为规范与统一标准,不推荐使用。)
With partdata as
  
SELECT ROWNUM AS ROWNO, TT.*  
    
FROM   (Select * 
                   
from k_task T 
                   
where flight_date between to_date('20060501''yyyymmdd'
                                                       
and to_date('20060531''yyyymmdd'
                   
ORDER BY FACT_UP_TIME, flight_no) TT 
   
WHERE ROWNUM <= 20
   
Select * from partdata where rowno >= 10


--6另类语法 。(无ORDER BY写法)
With partdata as
  
Select ROWNUM AS ROWNO, T.* 
    
From K_task T 
    
where Flight_date between to_date('20060501''yyyymmdd'
                                        
and to_date('20060531''yyyymmdd'
     
AND ROWNUM <= 20
  
Select * from partdata where Rowno >= 10;
<think>好的,我现在需要回答用户关于Oracle分页查询SQL示例的问题。首先,我得回忆一下Oracle分页的常用方法。记得Oracle通常使用ROWNUM或者ROW_NUMBER()函数来实现分页,这和MySQL的LIMIT或者PostgreSQL的LIMIT/OFFSET不同。 用户可能需要一个具体的示例,所以我应该先写出基本的语法结构。常见的分页方法是三层嵌套查询。最内层排序,中间层应用ROWNUM,外层筛选范围。比如,要查第21到40条数据,内层先排序并生成ROWNUM,中间层生成RN,外层用BETWEEN。不过根据引用[2]里的内容,这样的三层结构可能效率不高,因为外层过滤可能无法推到内层查询,导致中间层返回所有数据,外层再进行筛选,效率较低。 那有没有更高效的方法呢?引用[2]提到第二个查询语句,使用ROWNUM <= 40,然后外层用RN >=21。这样,Oracle可以将ROWNUM的条件推到内层,减少数据量。所以应该推荐用户使用这种方式,即先过滤ROWNUM <= 最大行数,再在外层筛选最小行数以上的部分。 然后,我需要给出具体的示例,比如查询第2页,每页10条,也就是11-20条。这时候,内层先排序,然后中间层用ROWNUM <=20,外层再用RN >=11。这样结构会更高效。 还要注意,使用ROW_NUMBER()函数的方法,这可能更直观。比如用OVER子句排序,然后筛选rn的范围。不过这种方法是否在性能上和ROWNUM的方式有差异呢?可能需要考虑,但用户可能只需要示例,所以可以两种都给出。 另外,需要注意在Oracle 12c及以上版本,可以使用FETCH NEXT和OFFSET,这样更简便。如果用户使用的是较新版本,这个语法会更直观。所以应该提到这一点,并给出示例。 现在,整理步骤:先介绍传统三层ROWNUM方法,然后说明优化后的两层方法,再提到ROW_NUMBER()的窗口函数方式,最后提到12c的新特性。同时,需要强调性能优化,如引用[2]提到的CBO优化,外层条件是否能被推入内层查询,影响效率。 还要确保SQL语法正确,比如别名的使用、分号的位置等。然后生成相关问题,可能涉及性能优化、不同版本的区别、其他数据库的分页方式比较等。</think>### Oracle 分页查询 SQL 示例 在 Oracle 数据库中,分页查询通常通过 **`ROWNUM` 伪列**或 **`ROW_NUMBER()` 窗口函数**实现。以下是具体实现方式及优化建议: --- #### 1. 使用 `ROWNUM` 的传统分页方法 通过三层嵌套查询实现分页语法结构如下: ```sql SELECT * FROM ( SELECT t.*, ROWNUM AS rn FROM ( SELECT * FROM 表名 ORDER BY 排序列 ) t WHERE ROWNUM <= 最大行数 ) WHERE rn >= 最小行数; ``` **示例**:查询第 2 页数据(每页 10 条,即第 11-20 条) ```sql SELECT * FROM ( SELECT t.*, ROWNUM AS rn FROM ( SELECT * FROM employees ORDER BY hire_date ) t WHERE ROWNUM <= 20 -- 最大行数 = 当前页 * 每页条数 ) WHERE rn >= 11; -- 最小行数 = (当前页 - 1) * 每页条数 + 1 ``` **优化说明**: 将 `ROWNUM <= 20` 放在中间层查询,Oracle 可将此条件推入内层查询,减少处理的数据量,提升效率[^2]。 --- #### 2. 使用 `ROW_NUMBER()` 窗口函数 通过窗口函数直接生成行号,语法更简洁: ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY 排序列) AS rn FROM 表名 t ) WHERE rn BETWEEN 最小行数 AND 最大行数; ``` **示例**:查询第 3 页数据(每页 5 条,即第 11-15 条) ```sql SELECT * FROM ( SELECT e.*, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn FROM employees e ) WHERE rn BETWEEN 11 AND 15; ``` --- #### 3. Oracle 12c 及以上版本的新语法Oracle 12c 开始,支持 `OFFSET-FETCH` 语法,类似其他数据库的 `LIMIT/OFFSET`: ```sql SELECT * FROM 表名 ORDER BY 排序列 OFFSET 跳过行数 ROWS FETCH NEXT 每页条数 ROWS ONLY; ``` **示例**:跳过前 20 行,取 10 条数据 ```sql SELECT * FROM employees ORDER BY employee_id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY; ``` --- ### 性能优化建议 1. **优先使用 `ROWNUM` 分页**:在旧版本中,`ROWNUM` 的性能通常优于 `ROW_NUMBER()`。 2. **减少排序开销**:确保 `ORDER BY` 的列有索引。 3. **避免深层分页**:分页越深(如第 1000 页),性能越低。可通过条件过滤优化(如 `WHERE id > 上次最大值`)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值