当前位置: 首页 > 科技观察

Oracle数据库知识点ROWNUM

时间:2023-03-12 00:12:28 科技观察

知识点内容ROWNUM是一个伪列,用于标识从一个表或一组连接(JOIN)表中查询数据时返回记录的顺序。Oracle在执行select查询时,会按照返回行的顺序为行分配一个序号:第一个返回行的序号为1,第二个行的序号为2,依此类推。这个序号就是每一行的rownum。ORACLE中ROWNUM使用总结对于Oracle的rownum问题,很多资料说不支持>,>=,=,between...and,只能用上面的符号(<,<=,!=),not>,>=,=,between..and会提示SQL语法错误,但往往找不到一条记录,还会出现看似莫名其妙的结果,其实只要理解rownum伪的含义就可以了专栏这应该不足为奇。它也是一个伪列。rownum和rowid有点不同。下面的例子说明:假设表t1(c1)有20条记录。如果使用selectrownum,c1fromt1whererownum<10,只要使用小于号,结果很容易在概念上与一般理解一致,所以应该没有疑问。但是如果你使用selectrownum,c1fromt1whererownum>10(如果你写这样的查询语句,此时你应该是想获取表中的最后10条记录),你会发现显示的结果应该是让你下来,也许你还在疑惑是不是有人删除了一些记录,然后查看记录的数量,还有20条记录?哪里有问题?先了解一下rownum的含义。因为ROWNUM是添加到结果集中的伪列,即先找到结果集后添加的列(强调:先要有结果集)。简单的说,rownum就是符合条件的结果的序号。它总是从1开始。所以你选择的结果不可能没有1,而是有其他大于1的值。所以你不能指望得到如下结果集:11aaaaaaaa12bbbbbbb13cccccccc...........rownum>10就没有记录了,因为如果第一项不满足,你去掉它,第二个ROWNUM又变成了1,所以永远不会有满足条件的记录。或者你可以这样理解:ROWNUM是一个序列,就是oracle数据库从数据文件或缓冲区中读取数据的顺序。它得到第一条记录,rownum值为1,第二条为2,依此类推。如果使用>,>=,=,between...等这些条件,因为从buffer或者数据文件中获取的第一条记录的rownum为1,所以会被删除,然后bar会被去掉,但是它的rownum还是1,删除了,以此类推,没有数据了。有了上面从不同方面建立的rownum的概念,我们可以理解使用rownum的几种现象:1.selectrownum,c1fromt1whererownum!=10为什么返回的是前9条数据?和selectrownum,c1fromt1whererownum<10返回的结果集一样吗?因为查询结果集,显示第9条记录后,后面的所有记录都是!=10,或者>=10,所以只显示前9条记录。也可以这样理解,rownum为9之后的记录的rownum为10,因为条件是!=10,所以去掉,后面的记录追加,rownum为10,就可以了也被删除。如果出现故障,则只会显示前9条记录。2、为什么rownum>1时找不到记录,而rownum>0或rownum>=1时却一直显示所有记录,因为rownum是在查询结果集后面加上的,总是从1开始的。3.为什么使用1到10之间或者0到10之间可以找到结果,但是2到10之间不能找到结果,原因和上面一样,因为rownum总是从1开始,从上面可以看出,任意当你想丢弃rownum=1记录时是错误的。在结果集中是不可或缺的。如果没有rownum=1,就像空中楼阁,无法存在,所以你的rownum条件必须包含1。但是如果你只是想使用rownum>10的条件,你需要先使用嵌套语句生成rownum,然后查询它。select*from(seletrownumasrn,t1.*fromawhere...)whereern>10一般代码中结果集是这样分页的。另外:rowid和rownum虽然都叫伪列,但是它们的存在方式不同。rowid可以说是物理存在的,表示表空间中记录的最大位置ID,在DB中的最大值。只要记录没有被移动,rowid就不会改变。相对于表,rowid就像是表中的一个通用列,所以如果以rowid作为条件,就没有rownum了。另请注意:rownum不能以任何基表的名称为前缀。2.实验过程为了更清楚地展示ROWNUM的用法,这里做了一些简单的实验。例如表:student(学生)表,表结构为:ID char(10)--学号name VARCHAR2(20) --namecreatetablestudent(IDchar(6),nameVARCHAR2(20));insertintostudentvalues('200001','张毅');insertintostudentvalues('200002','王二');insertintostudentvalues('200003','李三');insertintostudentvalues('200004','赵Si');犯罪;1、对于等于某个值的查询条件,如果要查找student表中第一个学生的信息,可以使用rownum=1作为条件。但是如果我想在student表中查找第二个学生的信息,使用rownum=2是找不到数据的。因为rownum是从1开始的,但是在rownum等于判断的时候认为1以上的自然数为假条件,所以rownum=n(n>1的自然数)是找不到的。SQL>selectrownum,id,namefromstudentwhererownum=1;(可以用来限制返回记录的条数,保证不报错,如:隐式游标)SQL>selectrownum,id,namefromstudentwhererownum=1;ROWNUMIDNAME----------------------------------------------1200001张SQL>selectrownum,id,namefromstudentwhererownum=2;ROWNUMIDNAME-------------------------------------------------2。如果rownum大于某个值,如果要查找第二行之后的记录,当rownum>2时,是找不到记录的。原因是rownum总是从1开始的伪列,Oracle认为rownum>n(n>1的自然数)的条件还是不成立,所以查不到记录SQL>selectrownum,id,namefromstudentwhererownum>2;ROWNUMIDNAME第二行之后的记录呢?可以使用下面的子查询方法来解决。注意子查询中的rownum必须有别名,否则找不到记录。这是因为rownum不是某个表的列。如果没有别名,就无法知道rownum是子查询的列还是主查询的列。.SQL>select*from(selectrownumno,id,namefromstudent)whereno>2;NOIDNAME3200003李三4200004赵四SQL>select*from(selectrownum,id,namefromstudent)whererownum>2;ROWNUMIDNAME3.rownum查找第三条记录之前的记录。当使用rownum<3时,可以得到两条记录。显然rownum认为rownum1)的自然数)条件为真,所以可以查到记录。SQL>selectrownum,id,namefromstudentwhererownum<3;ROWNUMIDNAME1200001Zhang12200002Wang2总结以上几种情况,可能有时候需要查询某个范围内rownum的数据,那怎么办呢?从上面我们可以看出rownum对小于某个值的查询条件人为为真,rownum直接认为大于某个值的查询条件为假,但是可以间接转换为被认为是真实的。那么你必须使用子查询。比如查询第二行和第三行之间的rownum数据,包括第二行和第三行数据,那么我们只能写如下语句,先让它返回小于等于三的记录行,然后在主查询中确定新rownum的alias列大于等于2的记录行。但是这样的操作会影响大型数据集的速度。SQL>select*from(selectrownumno,id,namefromstudentwhererownum<=3)whereno>=2;NOIDNAME--------------------------------------------------2200002王二3200003李三4.rownum和排序oracle中的rownum是取数据时产生的序号,所以如果要指定排序的数据要到指定的rowmun行数据,一定要注意。SQL>selectrownum,id,namefromstudentorderbyname;ROWNUMIDNAME3200003李三2200002王二1200001张毅4200004赵四可见rownum并不是根据name列生成的序号。系统按照记录插入的顺序对记录进行编号,rowid也是按顺序分配的。为了解决这个问题,必须使用子查询SQL>selectrownum,id,namefrom(select*fromstudentorderbyname);ROWNUMIDNAME---------------------------------------1200003李三2200002王二3200001张仪4200004赵四这样按名字排序,正确的序号用rownum标示(从小到大大的)。5、使用rownum分页显示方法方法一:SELECT*FROM(SELECTROWNUMr,e.*FROMempeWHEREROWNUM<=10)WHEREr>=5;方法二:SELECT*FROM(SELECTROWNUMr,e.*FROMempe)WHERErBETWEEN***ND10;方式三:SELECT*FROMempWHEREROWNUM<=10MINUSSELECT*FROMempWHEREROWNUM<5;