zoukankan      html  css  js  c++  java
  • Oracle的rownum原理

    Oracle中,按特定条件查询前N条记录,用个rownum就搞定了:
    SQL> select * from dept where rownum<3;

    而对rownum用">",会失败: 
    SQL> select * from dept where rownum>3;

    Oracle中rownum背后的机制: 
    1. Oracle执行SQL,得到第一行,rownum=1;
    2. 判断得到的这一行是否满足条件。如果满足条件,返回此行,rownum=1;如果不满足条件,丢弃此行,继续读取下一行。
    3. 读取下一行(如果上一步骤中找到满足条件的行),若满足条件,则rownum+1;否则rownum保持不变。
    4. 重复3的动作,直到fetch完表中的数据。

     

    了解了原理,就知道rownum>3不会成功,因为在第2步的时候查询出的行已经被丢弃,第3步查出来的rownum仍然是1,这样永远也不会成功。同样道理,rownum如果单独用=,也只有在rownum=1时才有用。
    对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,而且rownum不能以任何表的名称作为前缀。

     举例说明:
    SQL> select * from dept;
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK
            20 RESEARCH       DALLAS
            30 SALES          CHICAGO
            40 OPERATIONS     BOSTON

    (1) rownum 对于等于某值的查询条件
    如果希望找到部门表中第一条部门的信息,可以使用rownum=1作为条件。但是想找到部门表中第二条部门的信息,使用rownum=2结果查不到数据。因为rownum都是从1开始,但是1以上的自然数在rownum做等于判断是时认为都是false条件,所以无法查到rownum = n(n>1的自然数)。

    SQL> select rownum,deptno,dname from dept where rownum=1;(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标)
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK

    SQL> select rownum,deptno,dname from dept where rownum=2;
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK

    (2) rownum对于大于某值的查询条件
    如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的,原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum> n(n>1的自然数)这种条件依旧不成立,所以查不到记录。

    SQL> select * from dept where rownum>3;
    未选定行

    那如何才能找到第二行以后的记录?可以使用以下的子查询方法来解决。

    注意:子查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询的列还是主查询的列。

    SQL> select * from (select rownum rn,deptno,dname from dept) where rn>2;
            RN     DEPTNO DNAME
    ---------- ---------- --------------
            30 SALES               CHICAGO
            40 OPERATIONS     BOSTON

    (3) rownum对于小于某值的查询条件
    如果想找到第三条记录及以前的记录,当使用rownum<=3是能得到两条记录的。显然rownum对于rownum<=n((n>1的自然数)的条件认为是成立的,所以可以找到记录。

    SQL> select * from dept where rownum<=3;
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK
            20 RESEARCH         DALLAS
            30 SALES               CHICAGO

    (4) rownum对于区间查询条件
    从上可以看出rownum对小于某值的查询条件是为true的,rownum对于大于某值的查询条件直接认为是false的。那就必须使用子查询。
    例如要查询rownum在第二行到第三行之间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询中判断新的rownum的别名列大于等于二的记录行。但是这样的操作会在大数据集中影响速度。

    SQL> select * from (select rownum rn,deptno,dname from dept where rownum<=3) where rn>=2;
            RN     DEPTNO DNAME
    ---------- ---------- --------------
             2         20 RESEARCH
             3         30 SALES

    (5) rownum和排序
    Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。

    SQL> select rownum,deptno,dname from dept order by dname;
        ROWNUM     DEPTNO DNAME
    ---------- ---------- --------------
             1         10 ACCOUNTING
             4         40 OPERATIONS
             2         20 RESEARCH
             3         30 SALES

    可以看出,rownum并不是按照dname列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。为了解决这个问题,必须使用子查询。

    SQL> select rownum,deptno,dname from(select * from dept order by dname);
        ROWNUM     DEPTNO DNAME
    ---------- ---------- --------------
             1         10 ACCOUNTING
             2         40 OPERATIONS
             3         20 RESEARCH
             4         30 SALES

    这样就成了按dname排序,并且用rownum标出正确序号(有小到大)。

     

  • 相关阅读:
    JS(react)里面Json、String、Map、Object之间的转换
    react里面的几个内容
    object.assign的理解
    buffers与cached的区别
    vncserver错误
    Ubuntu可视化jupyter notebook
    ubuntu可视化桌面安装问题
    素数序列的生成及其应用 Version 2.2
    demo14-修改标签里面的属性
    demo13-修改元素的内容
  • 原文地址:https://www.cnblogs.com/toughhou/p/3778753.html
Copyright © 2011-2022 走看看