做过Oracle分页的人都知道由于Oracle中没有像MySql中limit函数以及SQLServer中的top关键字等,所以只能通过伪列的方式去满足分页功能,在此,不谈分页方法,只从根本上去介绍这两个伪列的用法与原理
rownum和rowid都是伪列,但是两者的根本是不同的
- rownum是根据sql查询出的结果给每行分配一个逻辑编号,所以你的sql不同也就会导致最终rownum不同
rowid是物理结构上的,在每条记录insert到数据库中时,都会有一个唯一的物理记录 (不会变)
下面以scott用户的emp表为例.
一、ROWNUM伪列
ROWNUM伪列是Oracle首先进行查询获取到结果集之后在加上去的一个伪列,这个伪列对符合条件的结果添加一个从1开始的序列号,先看一个例子:
SELECT ROWNUM,empno,ename,job FROM emp WHERE deptno = 30;
结果如下:
可以看到确实添加了一列从1开始的序列号,那么有了这个伪列,就可以完成好多提取数据的工作,比如提取emp表中前5条数据,SQL如下:
SELECT ROWNUM,empno,ename,job FROM emp WHERE ROWNUM < 6;
ROWNUM是动态的,也就是必须先有查询到的结果集,然后再给这个结果集加上一个列,比如给结果集中的第一条数据的ROWNUM的值为1,依次类推,如果此时这样写:
SELECT ROWNUM,empno,ename,job FROM emp WHERE ROWNUM > 5 AND ROWNUM <= 10;
当生成结果集时,Oracle首先会产生一条ROWNUM为1的记录,显然不符合条件,那么同样会继续产生第二条数据,同样标识ROWNUM为1,该条记录同样继续被过滤掉,后续生成的ROWNUM依然为1,因此上述查询语句不会有任何查询结果,所以如果想要使上述结果有满足条件的结果集,必须使用子查询(把rownum查出来后放在一个虚表中作为这个虚表的字段再根据条件查询),代码如下:
SELECT * FROM (SELECT ROWNUM nums,emp.* FROM emp) WHERE nums > 5 AND nums <= 10;
子查询部分固定表里面数据的记录编号,外层查询过滤子查询里面固定的记录编号就可以实现Oracle分页!
二、ROWID伪列
同ROWNUM伪列不同的是,它是物理存在的,ROWID是一种数据类型,它使用基于64bit编码的18个字符来唯一标识一条记录物理位置的一个ID,类似于Java中一个对象的哈希码,都是为了唯一标识对应对象的物理位置,需要注意的是ROWID虽然可以在表中进行查询,但是其值并未存储在表中(既然是伪列,就说明表中并不会物理存储ROWID的值),所以不支持增删改操作,下面看个例子:
SELECT ROWNUM,ROWID,empno,ename,job FROM emp WHERE ROWNUM <= 5;
结果如下:
可以看到ROWID确实由18个字符组成,组成结构如下:
数据对象编号 | 文件编号 | 块编号 | 行编号 |
OOOOOO | FFF | BBBBBB | RRR |
得到一个如下的数据库表
CREATE TABLE dept_bak AS SELECT * FROM dept; INSERT INTO dept_bak SELECT * FROM dept;
很明显,数据有重复的,当然你也可以用一个很原始的方法,就是将有重复记录的表中的数据导到另外一张表中,最后再倒回去。
SQL>create table emp_tmp as select distinct* from emp;
SQL>truncate table emp; //清空表记录
SQL>insert into empselect * from emp_tmp;//将临时表中的数据添加回原表
但是要是emp的表数据是百万级或是更大的千万级的,那这样的方法显然是不明智的,因此我们可以根据rowid来处理,rowid具有唯一性,查询时效率是很高的,那么就可以利用这个特性去重,简单示例代码如下:
DELETE FROM dept_bak
WHERE ROWID NOT IN(SELECT MIN(ROWID)
FROM dept_bak GROUP BY DEPTNO);
再例如,学生表中的姓名会有重复的情况,但是学生的学号是不会重复的,如果我们要删除学生表中姓名重复只留学号最大的学生的记录,怎么办呢?可以参考如下做法:
DELETE FROM stu a
WHERE ROWID NOT IN (SELECT MAX(ROWID)
FROM stu b
WHERE a.name = b.name
AND a.stno < b.stno);
除了上述之外还有好多作用,详情参照Oracle官方文档!,在此不多做叙述!