• Oracle


    测试表 EMP

    SELECT * FROM EMP;

    ROWNUM(顺便对比下 ROWID)

    ROWID 和 ROWNUM 都是伪列,但含义完全不同。

    • ROWID 是物理地址,用于定位 Oracle 中具体数据的物理存储位置,用于定位数据表中某条数据的位置,是唯一的、也不会改变。
    • ROWNUM 则是 SQL 的输出结果排序。表示查询某条记录在整个结果集中的位置, 同一条记录,查询条件不同,对应的 ROWNUM 是不同的,而 ROWID 是不会变的。
    • ROWID 是相对不变的,ROWNUM 会变化,尤其是使用 ORDER BY 的时候。

    ROWNUM 对性能的影响:

    • ROWNUM 可以避免 Oracle 在磁盘上进行排序。ROWNUM 无法避免全表扫描的发生,但是它可以避免对整个表数据的排序操作,在指定了 ROWNUM 后,排序操作在内存中可以轻松完成。

    WHERE ROWNUM >= 1、ROWNUM >= 0、ROWNUM > 0,查询结果一致

    SELECT * FROM EMP WHERE ROWNUM >= 1;
    SELECT * FROM EMP WHERE ROWNUM >= 0;
    SELECT * FROM EMP WHERE ROWNUM > 0;

    WHERE ROWNUM = 1,查询结果为一条记录,没毛病

    SELECT * FROM EMP WHERE ROWNUM = 1;

    WHERE ROWNUM > 1 或者 ROWNUM = 一个比 1 大的数(ROWNUM = 2),查询结果为空

    SELECT * FROM EMP WHERE ROWNUM > 1;-- 查询的不是第 2~14 条记录,查询结果为空! 
    SELECT * FROM EMP WHERE ROWNUM = 2;-- 以为查询的结果是第 2 条记录吗?不好意思,查询结果为空!
    SELECT * FROM EMP WHERE ROWNUM >= 10;-- 是不是以为查询的结果是表中第 10~14 条记录,但是明显不是,查询结果为空!

    上面几组 SQL,执行结果,解析如下:

    • ROWNUM > 0、ROWNUM >= 0、ROWNUM >=1,如果 WHERE ROWNUM 条件如前面三种的话,查询的结果为 ROWNUM 从 1 开始,到最后一条记录(即全部记录)
    • 原因是:ROWNUM 作为 Oracle 表记录的伪列,从 1 开始,即ROWNUM(1、2、3、4、5...、14),ROWNUM > 1,对于第一行来说,并不是真值,因为 ROWNUM 从 1 开始,ROWNUM > 1,真值为 false,而后表记录中原 ROWNUM 为 2 的记录补上,新的 ROWNUM 为 1~13,同理,ROWNUM > 1 真值还是 false,然后初始记录 ROWNUM = 3 的记录补上,新的 ROWNUM 为 1~12,以此类推,ROWNUM > 1 结果真值永远为 false,所以,查询的结果集总为空!
    • 结果可知,SELECT * FROM EMP WHERE ROWNUM [condition],condition 条件永远不要使用 ROWNUM > ? 或者 ROWNUM = n(n!=1),因为这样意义不大。

    WHERE ROWNUM < 或 <= n(n 大于 1)

    SELECT * FROM EMP WHERE ROWNUM <= 10;-- 前 10 条记录

    解析:

    • SELECT * FROM EMP WHERE ROWNUM <= 10,结果和预期一致。
    • ROWNUM <= 10,第一条记录 ROWNUM 为 1,条件 ROWNUM <=10 为 true,然后 ROWNUM 增长为 2,条件仍为 true,直到 ROWNUM 增长为 10,条件仍为 true,ROWNUM 增长为 11,ROWNUM <= 10 条件为 false,此时原记录中 ROWNUM = 12 的记录补上,ROWNUM 仍为 11,ROWNUM <= 10 条件恒为 false。则查询结果集是:ROWNUM 从 1 到 10 的记录

    WHERE ROWNUM != n(n 大于 1)

    SELECT * FROM EMP WHERE ROWNUM != 10;

    分析过程,和上面类似。ROWNUM 从 1~9,ROWNUM != 10 结果都为 ture,当 ROWNUM 增长到 10,ROWNUM != 10,判断条件为 false,所以只查询出第 1~9 条记录。

    BETWEEN...AND...

    SELECT * FROM EMP WHERE ROWNUM BETWEEN 1 AND 10;

    BETWEEN 2 AND n,从 2 或者 任何大于 1  开始,到 n

    SELECT * FROM EMP WHERE ROWNUM BETWEEN 2 AND 10;-- 查询为空!

     分析:

    • BETWEEN START AND END,ROWNUM 总是从 1 开始,所以 START 去和数据文件或者缓冲区中读取读取第一条记录(ROWNUM 为 1),不符合,所以 ROWNUM = 1 这条记录从临时表中删除,下一条记录补上,作为新的记录 ROWNUM  =1 继续比较 ,真值仍为 false,以此类推,导致查询结果集为空!
    • 所以,想直接通过 WHERE ROWNUM BETWEEN START AND END 来进行分页查询,不奏效。为此就要借助子查询,将 ROWNUM 伪列,作为字段,在子查询中查询出来,然后做分页查询。

    Oracle 利用 ROWNUM 做分页查询:

    SELECT M.*
      FROM (SELECT ROWNUM AS RN, T.* FROM EMP T WHERE ROWNUM <= 8) M
     WHERE RN >= 3;
    SELECT M.*
      FROM (SELECT ROWNUM AS RN, T.* FROM EMP T) M
     WHERE RN BETWEEN 3 AND 8;

  • 相关阅读:
    【力扣】461. 汉明距离
    【力扣】206. 反转链表
    【力扣】169. 多数元素
    LINQ 基本子句之三 let
    LINQ 基本子句之二 join
    LINQ 基本子句之一 (select/where/group/into)
    关于Console的Main(String[] args)参数输入
    SQL Common Sense 碎片一
    简单组合条件查询
    关于SQL 系统自带存储过程的使用 (一)
  • 原文地址:https://www.cnblogs.com/ikoo4396/p/7250257.html
Copyright © 2020-2023  润新知