最常用的两个伪列:rownum和rowid。
行号的产生:
行号的排序:
示例:
--需求:查询出所有员工信息,按部门号正序排列,并且显示默认的行号列信息。
SELECT ROWNUM,t.* FROM emp t ORDER BY deptno;--order by 的原理:将查询结果(
此时行号已经有了,已经和每一行数据绑定了)进行排序。
- --order by是查询语句出来的结果之后再排序的,rownum是在查询出来结果的时候产生。order by
不会影响到行号
--先排序,再查询
SELECT ROWNUM,t.* FROM
(
SELECT * FROM emp ORDER BY deptno
) t
结论:
利用行号进行数据分页:
mysql如何分页?
select * from table limit m,n
其中m是指记录开始的index,从0开始,表示第一条记录
n是指从第m+1条开始,取n条。
select * from tablename limit 3,3
即取出第4条至第6条,3条记录
结论:Mysql使用limit的关键字可以实现分页,但Oracle没有该关键字,无法使用该方法进行分页。
示例:
--需求:根据行号查询出第四条到第六条的员工信息。
SELECT ROWNUM,t.* FROM emp t;
SELECT ROWNUM,t.* FROM emp t WHERE ROWNUM >=4 AND ROWNUM<=6;
--rownum只能使用< <=,不能使用> >=符号,
SELECT ROWNUM,t.* FROM emp t WHERE ROWNUM<=6;
--方案:可以使用子查询
SELECT rownum,t2.* FROM
(
SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM<=6--此时子查询的rownum已经变成了
虚表的一个列
) t2--尽量让虚表尽量小
WHERE t2.r >=4
--优化
SELECT * FROM
(
SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6
) WHERE r >=4;
--结果指定字段
SELECT empno,ename,job FROM(
SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6
) WHERE r >=4;
--按照薪资的高低排序再分页
SELECT * FROM
(
SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6 ORDER BY sal DESC
) WHERE r >=4 ;
分析原因:
rownum只能使用< <=,不能使用> >=符号,原因是:Oracle是基于行的数据库,行号永远是从1开始,即必须有第一行,才有第二行。
ROWID(记录编号):是表的伪列,是用来唯一标识表中的一条记录,并且间接给出了表行的物理位置,定位表行最快的方式。
ROWID的产生:
提示:rownum默认的排序就是根据rowid
ROWID的作用:
这里列举两个常见的应用:
关于主键和rowid的区别:
示例:
需求:删除表中的重复数据,要求保留重复记录中最早插入的那条。(DBA面试题)
--查看rowid
SELECT t.*,ROWID FROM emp t;
--需求:删除表中的重复数据,要求保留重复记录中最早插入的那条。(面试题)
--准备测试表和测试数据:
--参考建表语句如下:
-- Create table
create table test
(
id number,
name varchar2(50)
) ;
--插入测试数据
INSERT INTO TEST VALUES(1,'xiaoming');
INSERT INTO TEST VALUES(2,'xiaoming');
INSERT INTO TEST VALUES(3,'xiaoming');
COMMIT;
SELECT * FROM TEST ;
--通过rowid,剔除重复xiaoming,保留最早插入的xiaoming
SELECT t.*,ROWID FROM TEST t;
--删除的的时候,可以先查询你要删除的东东
SELECT t.*,ROWID FROM TEST t WHERE ROWID > (SELECT MIN(ROWID) FROM TEST);
DELETE FROM TEST t WHERE ROWID > (SELECT MIN(ROWID) FROM TEST);
--语句有缺点:条件不足,会只保留一条数据,误删其他数据
--重新插入测试数据
INSERT INTO TEST VALUES(1,'xiaoming');
INSERT INTO TEST VALUES(2,'xiaoming');
INSERT INTO TEST VALUES(3,'xiaoming');
INSERT INTO TEST VALUES(4,'Rose');
INSERT INTO TEST VALUES(5,'Rose');
COMMIT;
--剔除重复数据
SELECT * FROM TEST WHERE ROWID NOT in(SELECT MIN(ROWID) FROM TEST GROUP BY NAME);
DELETE FROM TEST WHERE ROWID NOT in(SELECT MIN(ROWID) FROM TEST GROUP BY NAME);
注意:删除重复记录一定要小心,万一你的条件有问题,就会删错数据.建议删除之前,可以先用查询查一下,看是否是目标数据。
数据一旦删除恢复比较麻烦,但可以恢复,采用日志回滚。一般不要轻易用。