Oracle rownum伪劣

【Oceanbase系列】——OceanBase SQL执行计划 一、前言 能点开我这篇文章的,相信应该都是有点数据库背景的,SQL语句在不同的人手中会写出不同的语句形式,比如经常遇到的SQL慢查询,这时候往往需要针对SQL进行优化。而像orancle和mysql中为保证SQL语句能够高效的运行,提供了一个Explain的命令,用来对SQL语句进行语义分析,供开发者来针对SQL进行优化。当然了 oceanbase是蚂蚁自研的分布式数据库,支持mysql和orancle两种模式,既然敢吹分布式这个牛,那这里边的执行计划就不得不提一下,毕竟你的sql是要跑在分布式... 阅读详情
一、对rownum的说明

   关于Oracle 的 rownum 问题,很多资料都说不支持SQL语句中的“>、>=、=、between...and”运算符,只能用如下运算符号“<、<=、!=”,

   并非说用“>、>=、=、between..and”时会提示SQL语法错误,而是经常是查不出一条记录来,还会出现似乎是莫名其妙的结果来。

   其实,只要理解好了这个 rownum 伪列的意义就不应该感到惊奇。

   rowid 与 rownum 虽都被称为伪列,但它们的存在方式是不一样的:

   rowid 是物理存在的,表示记录在表空间中的唯一位置ID,在DB中是唯一的。只要记录没被搬动过,rowid是不变的。

   rowid 相对于表来说又像表中的一般列,所以,以 rowid 为条件就不会有rownum那些莫名其妙的结果出现。

   另外还要注意:rownum不能以任何基表的名称作为前缀。

   对于下面的SQL语句

   SQL>select rownum,id,age,name from loaddata where rownum > 2;

    ROWNUM ID     AGE NAME
    ------- ------ --- ------

    rownum>2,没有查询到任何记录。

    因为rownum总是从1开始的,第一条不满足去掉的话,第二条的rownum 又成了1。依此类推,所以永远没有满足条件的记录。

    可以这样理解:rownum是一个序列,是Oracle数据库从数据文件或缓冲区中读取数据的顺序。

    它取得第一条记录则rownum值为1,第二条为2。依次类推。

    当使用“>、>=、=、between...and”这些条件时,从缓冲区或数据文件中得到的第一条记录的rownum为1,不符合sql语句的条件,会被删除,接着取下条。

    下条的rownum还会是1,又被删除,依次类推,便没有了数据。


二、对rownum使用中几种现象的分析说明
  
    有了以上从不同方面建立起来的对rownum的概念,下面认识使用rownum的几种现象:

    (1) select rownum,id,age,name from loaddata where rownum != 10 为何是返回前9条数据呢?
     为什么它与 select rownum,id,age,name from loaddata where rownum < 10 返回的结果集是一样的?

     因为是在查询到结果集后,显示完第9条记录后,之后的记录都是 != 10或者 >=10,所以只显示前面9条记录。

     也可以这样理解,rownum为9后,取的记录的rownum为10,因条件为 !=10,所以删掉。然后取下一条,其rownum又是10,也删掉。以此类推。

     所以只会显示前面9条记录。


    (2)什么rownum >1时查不到一条记录,而 rownum >0或rownum >=1 却总显示所有记录。

     这是因为rownum是在查询到的结果集后,再加上去的,它总是从1开始的。


    (3)为什么between 1 and 10 或者 between 0 and 10 能查到结果,而用 between 2 and 10 却得不到结果。

     原因同上:因为 rownum总是从1开始。


     从上可得,任何时候想把rownum = 1这条记录抛弃是不对的。它在结果集中是不可或缺的。

     少了rownum=1就像空中楼阁一般不能存在。所以,rownum条件要包含到1。


三、一些rownum实际运用的例子:

     -----------
     --sql建表脚本

     create table LOADDATA
     (
         ID   VARCHAR2(50),
         AGE  VARCHAR2(50),
         NAME VARCHAR2(50)
     );
     -----------

    (1) rownum 对于“等于某值”的查询条件

     如果希望找到loaddata表中第一条记录的信息,可以使用rownum=1作为条件。

     但是想找到loaddata表中第二条记录的信息,使用rownum=2,是查不到数据的。

     因为rownum都是从“1”开始。

     “1”以上的自然数,在rownum做等于判断是时认为都是false条件,所以无法查到rownum = n(n>1的自然数)。


      select rownum,id,age,name
      from loaddata
      where rownum = 1;   --可以用在限制返回记录条数的地方,保证不出错,如:隐式游标。


    SQL>select rownum,id,age,name from loaddata where rownum = 1;

    ROWNUM ID     AGE NAME
    ------- ------ --- ------
         1 200001 22   AAA


    SQL>select rownum,id,age,name from loaddata where rownum = 2;

    ROWNUM ID     AGE NAME
    ------- ------ --- ------


   注:SQL>select rownum,id,age,name from loaddata where rownum != 3; --返回的是前2条记录。

     ROWNUM ID     AGE NAME
    ------- ------ --- ------
         1 200001 22   AAA
         2 200002 22   BBB


  (2)rownum对于大于某值的查询条件

    如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的。

    原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum> n(n>1的自然数)这种条件依旧不成立,所以查不到记录。

    SQL>select rownum,id,age,name from loaddata where rownum > 2;

    ROWNUM ID     AGE NAME
    ------- ------ --- ------


    那如何才能找到第二行以后的记录?

    可以使用下面的子查询方法来解决。

    注意子查询中的rownum必须要有别名,否则仍然会查不到记录,这是因为rownum不是某个表的列。

    如果不起别名的话,无法知道rownum是子查询的列,还是主查询的列。


     SQL>select rownum,id,age,name from(select rownum no ,id,age,name from loaddata) where no > 2;

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         3 200003 22   CCC
         4 200004 22   DDD
         5 200005 22   EEE
         6 200006 22   AAA


     SQL>select * from(select rownum,id,age,name from loaddata) where rownum > 2;

     ROWNUM ID     AGE NAME
     ------- ------ --- ------



    (3)rownum对于小于某值的查询条件

     如果想找到第三条记录以前的记录,当使用rownum<3是能得到两条记录的。

     显然rownum对于rownum<n((n>1的自然数)的条件认为是成立的,所以可以找到记录。

     SQL> select rownum,id,age,name from loaddata where rownum < 3;

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         1 200001 22   AAA
         2 200002 22 BBB


     综上几种情况:

     可能有时候需要查询rownum在某区间的数据,从上可以看出rownum对小于某值的查询条件是认为true的。

     rownum对于大于某值的查询条件直接认为是false的,但是可以间接的让它转为认为是true的,那就必须使用子查询。

     例如要查询rownum在第二行到第三行之间的数据,包括第二行和第三行数据,那么只能写以下语句,先让它返回小于等于三的记录行,

     然后在主查询中判断新的rownum的“别名列”大于等于二的记录行。但是这样的操作会在大数据集中影响到检索速度。


     SQL>select * from (select rownum no,id,age,name from loaddata where rownum <= 3 ) where no >= 2; --必须是里小外大

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         2 200002 22 BBB
         3 200003 22   CCC


     也可以用这种方法实现:

     SQL>select rownum,id,age,name from loaddata where rownum < 4
         minus
         select rownum,id,age,name from loaddata where rownum < 2

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         2 200002 22 BBB
         3 200003 22   CCC



    (4)rownum和排序

     Oracle中的rownum的是在取数据的时候产生的序号。故,如在已排序的数据中,要求取出指定的rowmun行数据时,就需注意了。

     前提条件:loaddata表中已经insert了5条记录,最后一条记录id是200005,接着insert into loaddata values('200006','22','AAA');

     SQL>select rownum,id,age,name from loaddata;

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         1 200001 22   AAA
         2 200002 22   BBB
         3 200003 22   CCC
         4 200004 22   DDD
         5 200005 22   EEE
         6 200006 22   AAA


     SQL>select rownum ,id,age,name from loaddata order by name;

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         1 200001 22   AAA
         6 200006 22   AAA
         2 200002 22   BBB
         3 200003 22   CCC
         4 200004 22   DDD
         5 200005 22   EEE

     可以看出,rownum并不是按照name列来生成的序号。

     系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。

     为了解决这个问题,必须使用子查询

     SQL>select rownum ,id,age,name from (select * from loaddata order by name);

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         1 200001 22   AAA
         2 200006 22   AAA
         3 200002 22   BBB
         4 200003 22   CCC
         5 200004 22   DDD
         6 200005 22   EEE


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

     对于大数据量的时候,建议在order by 的字段上加主键或索引这样效率会提高很多。

     同样,返回中间的记录集:

     SQL>select * from ( select rownum ro,id,age,name from loaddata where rownum < 5 order by name ) where ro > 2; (先选再排序再选)

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         3 200002 22   BBB
         4 200003 22   CCC


     一般业务需求中,是需要先排序后,再返回中间记录集:

     SQL>select * from (select t.*,rownum ro from (select id,age,name from loaddata order by name ) t where rownum < 5 ) where ro>=2; (先排序再选再选)

     ROWNUM ID     AGE NAME
     ------- ------ --- ------
         3 200002 22   BBB
         4 200003 22   CCC

     注意此时的SQL语句写法,使用了多重(三层)嵌套。同时注意:rownum使用了“列别名”。

     实际上,该语句也是Oracle数据集一个经典的SQL语句分页算法:先排序,再选择rownum < 某页的最大值,再选择rownum > 某页的最小值。



四、一个实例:

    需求:假设不知道数据库里的数据规则和数量,要把所有的student数据打印到终端。

    解:rownum是伪列,在表里没有,数据库先是执行from book遍历book表。

        如果没有where条件过滤,则先做成一个结果集,然后再看select后面的条件,挑出合适的字段形成最后的结果集。

        如果有 where条件,则不符合条件的就会从第一个结果集中删除,后面的数据继续加进来判断。

        所以如果直接写rownum=2,或者rownum>10这样的语句就查不出数据。

        可以用一个子查询来解决这个问题:对于select rownum,id from book where rownum=2; 是查不出数据来的。


       declare
           v_number binary_integer;
           v_student student%rowtype;
       begin
           select count(*) into v_number from student;
           for i in 1..v_number loop
              select id,name,age into v_student from ( select rownum rn,id,name,age from student ) where rn=i;
              dbms_output.put_line('id: '||v_student.id||' name:'||v_student.name);
          end loop;
       end;

      rownum是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。

      简单的说 rownum 是对符合条件结果的序列号。

      它总是从1开始排起的。所以,选出的结果不可能没有1,反而有其他大于1的值。
SAP开发实战:用FI_DOCUMENT_CHANGE BAPI批量修改FB03凭证抬头和行项目文本(附完整ABAP代码) 本文详细介绍了如何使用SAP的FI_DOCUMENT_CHANGE BAPI批量修改FB03凭证抬头和行项目文本,提供完整的ABAP代码实现方案。通过该BAPI,开发者可以高效完成财务凭证的批量修改,确保数据一致性和审计合规性,显著提升SAP财务模块的运维效率。 阅读详情

相关推荐

国赛数学建模高教社杯历届优秀论文全集

包含了2004到2023年高教社的赛题及优秀论文。

BanDeng001的博客 3288

ROWNUM的相关知识点

一、对rownum的说明    关于Oracle 的 rownum 问题,很多资料都说不支持SQL语句中的“>、>=、=、between...and”运算符,只能用如下运算符号“    并非说用“>、>=、=、between..and”时会提示SQL语法错误,而是经常是查不出一条记录来,还会出现似乎是莫名其妙的结果来。    其实,只要理解好了这个 rownum 伪列的意义就不应

雅冰石的专栏 1089

某教育平台线上用户流失分析

本项目基于某教育平台的用户登录信息、用户个人信息以及用户课程学习记录三信息表,挖掘了平台流量以及用户流失等信息。使用python对数据进行预处理,使用tableau进行数据可视化分析。该教育平台正值窗口期,平台流量没有良好的留存水平,但有良好的发展趋势,需要深入分析用户留存率低,做好招新促活营销。该教育平台的基本盘在广东、湖北、河南、贵州等省份,线上教育的潜在用户可能更多分布在线下教育资源不充足、受疫情影响更为严重的地区。

fhy12的博客 1300

oracle 高效使用rownum来得到表中指定的几行数据

亲测有用

weixin_44288470的博客 1476

STM32F407+LAN8720A+LwIP实战:FreeModbus TCP从机功能开发指南

本文详细介绍了基于STM32F407和LAN8720A硬件平台,结合LwIP协议栈实现FreeModbus TCP从机功能的开发指南。内容涵盖硬件连接、LwIP移植、FreeModbus TCP从机实现、任务调度及调试技巧,为工业控制领域的以太网通信开发提供实用参考。

weixin_29190651的博客 546

【牛股启动线】副图指标使用技术说明,图文案例分享,通达信炒股指标

如上图,在紫色线在黑色虚线上时,在出现紫色柱线时,通常会出现强势拉升的行情​。柱线加长加上紫色线上扬,进场跟随做多抓强势行情,紫色柱线和紫色线同时做多持续则可以继续持股。如上图,副图指标【牛股启动线】,指标信号包括紫色线走势信号和紫色柱线信号,以及底部的四条虚线技术信号​,还有一条绿色的参考线,一条黑色的虚线两天分档线。如上图,参考买点,紫色柱线开始出现时进场买点,在上图标记的位置对应的就是进场买点​。紫色柱线加长+紫色线上扬,多头共振持股,行情继续拉升阶段,持股待涨或顺势​进场做多。

weixin_69760830的博客 1910

别名法在Oracle数据库注入中的用法详解

出于学习的目的研究了一下Oracle数据库中rownum的用法,现将学习中的收获分享给大家,同时分享一个在线Oracle练习平台的链接。

seek_2022的博客 3471

地震数据可视化必备:5分钟读懂SEGY道头字段全解析(含坐标定位指南)

本文深入解析了SEGY文件格式中道头坐标字段的提取与可视化方法。针对地震数据处理中的常见痛点,详细介绍了sx/sy、gx/gy等关键坐标字段的二进制解析、比例因子应用、单位转换及常见问题解决方案,并提供了实用的Python代码示例,帮助开发者实现从SEGY文件到三维空间可视化的完整流程。

echo99的专栏 1011

rowid 与 rownum ,视图与索引 ,表设计 ,DDL 和DML

--rowid 与 rownum --都做伪列存在 --rowid : 行记录的地址,行的唯一标识,数据插入到表中的是决定 --可以实现去重: 对没有主键|唯一字段的表中多条完全重复的数据,根据rowid实现去重 --去重: 如果表中存在主键或者唯一字段,直接 根据主键或者唯一字段去重 select rowid,rownum from dept; /* insert into tb_student values(1,'张三','语文',81); insert into tb_student va..

wangjinju77777的博客 375

基于三轴加速度计的塑料水管泄漏振动检测技术全解析

在流体力学与结构动力学领域,管道振动分析是评估系统健康状态的关键技术。其基本原理在于,当管道内流体状态发生异常(如泄漏)时,会引发管壁产生特定的机械振动信号。这项技术的核心价值在于实现了对管道系统的非侵入式、在线监测,能够提前预警潜在故障,避免资源浪费与次生灾害。在智慧城市与智能水务等应用场景中,它对于保障供水管网安全、提升运维效率具有重要意义。本文聚焦于如何利用高精度的三轴加速度计,精准捕捉塑料水管因泄漏产生的微弱振动,并通过信号处理与机器学习算法,构建一套从数据采集到泄漏识别与定位的完整工程解决方案。

weixin_32239523的博客 407

【25届数字IC秋招总结】面试经验10——紫光同芯

25届数字ic面试记录——紫光同芯

lalala0635的博客 862

给mysql或oracle查询,加伪劣排序rownum和row_number(),创建会话 你会吗?

注意MySQL在8.0版之前不支持ROW_NUMBER()函数,但是它们提供了一个会话变量。或者是row_number() over(order by xxx) 排序功能。写法为查询的时候在后面加rownum (不排序)oracle提供了加伪列给顺序的函数。连查完后定义一个初始化序列号即可。.....

Theshy08的博客 491

解锁RK1126与SC132GS摄像头适配密码:技术与代码全解析

本文详细介绍了瑞芯微RK1126芯片与SC132GS摄像头的适配方法。首先分析了RK1126的四核Cortex-A7处理器、Mali-T860 GPU等硬件特性,以及SC132GS的130万像素、全局快门等技术参数。重点阐述了基于MIPI CSI接口的硬件连接原理和基于V4L2框架的软件驱动设计,并提供了完整的初始化、数据采集和图像处理代码实现。针对常见连接和图像质量问题给出了解决方案,展现了该组合在智能安防、工业检测等领域的应用潜力,为开发者提供了实用的技术参考。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 1503

oracle和mysql实现分页查询

oracle实现分页查询 使用伪劣rownum实现分页查询 //可以运行 select rownum from emp where rownum<6; //不可以运行 select rownum from emp where rownum>6; //不可以运行,无结果 select rownum from emp where rownum<6 and rownum>3; //例题 假设每页显示3条,查询出第二页 查不出 select * from (select emp.*,r

小乌龟 3479

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Oracle 伪列: ROWNUM 应用与总结

ROWNUM 可以根据 SQL 返回结果, 进行动态生成序列值, 常用在: 1. TOP N 输出; 2. 分页; 3. 分组子排序(难点) 中

Thinking Notes 891

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

rownum sql值获取一个值_oracle中rownum和row_number()

row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。 与rownum的区别在于:使用rownum进行排序的时候是先对结果集加入伪劣rownum然后再进行排序,而row_number()在包含排序从句后是先排序再计算行号码。一、oracl...

weixin_42298969的博客 251

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

用ORACLE 中伪列rownum对查询结果进行排序

rownum含义解释: 1、rownum是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,   依此类推,这个伪字段可以用于限制查询返回的总行数。 2、rownum不能以任何基表的名称作为前缀。 使用方法: 现有一个商品销售表sale,表结构为: month    char(6)      --月份 sell    number(10,2)   --月销售金额

谢威的专栏 2476

oracle 使用rownum减少自定义函数的调用

ROWNUM Pseudocolumn --rownum 伪列 For each row returned by a query, the  ROWNUM  pseudocolumn returns a number  indicating the order in which Oracle selects the row from a table or set of joined row

FoKing的专栏 742

对oracle 中rownum 的理解

在Oracle中,要按特定条件查询前N条记录,用个rownum就搞定了。 select * from emp where rownum &lt;= 5 而且书上也告诫,不能对rownum用"&gt;",只能使用"&lt;=","&lt;","!=",这也就意味着,如果你想用 select * from emp where rownum &gt; 5 则是失败的。要知道为什么会失败,则需要了

前行 307

Oracle的伪列:ROWNUM

(以下是个人理解,无法保证完全正确) ROWNUM是一个伪劣: 1.功能是在每次查询时,返回结果集的顺序号,在输出时一步一步产生。 注:所谓的输出是指结果集生成时,而不是显示在电脑屏幕上的输出       2.ROWNUM只能执行&lt;,&lt;=运算,不能执行&gt;,&gt;=或一个区间运算between...and等。 3.ROWNUM与ORDER BY一起使用时,ROWNUM...

shuang的博客 215

oracle中分组排序函数用法

原文链接:http://xm-koma.iteye.com/blog/2078500                     http://zhidao.baidu.com/link?url=V3b-k4B8NHinJoV7KpN8ZnXXVFWpXqch9_gprsSWr1zoLF1_HIyanZ-IenMmBbQMWtdzm9FX8CCPzg9MPuXMla 项目开发中,我们有

732

mysql 添加伪列 如同oracle的rownum

alter table tablename add column columnname int(10);  set @rownum=0; update tablename set columnname=@rownum:=@rownum+1;

xue_tech的博客 647

Oracle数据库之数据伪劣

伪劣指的就是不存在于表中的列,但是该列又可以直接使用 如SYSDATE ROWNUM(开发中常用)、ROWID(数据库分析) 一、ROWNUM伪列 ROWNUM直接翻译就是行号 如果要显示行号就直接追加ROWNUM即可 ROWNUM会自动生成一个增长列的行号 常用的操作 select * from 表名 where rownum=1; #查看某个表的第一行,但是只能查看第一行 ...

weixin_42480196的博客 1046

转转转--oracle 去重并按时间排序取第一条

select t.* from (select a.*, row_number() over(partition by 需要分组的字段 order by 更新时间 desc) rw from 表 a) t where t.rw = 1 row_number()over(partition by col1 order by col2)...

weixin_30488085的博客 151

oracle rownum_,oracle中rownum和row_number()

row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。 与rownum的区别在于:使用rownum进行排序的时候是先对结果集加入伪劣rownum然后再进行排序,而row_number()在包含排序从句后是先排序再计算行号码。一、oracl...

weixin_30707165的博客 1302

Oracle数据库之ROWNUM与ROWID

Oracle数据库之ROWNUM与ROWID

zhang_java_11的博客 532
上一篇: 所理解Java中的堆和栈
下一篇: 与over函数结合的几个函数介绍
mm_tiny
博客等级 码龄15年 7粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值