1. 伪列

1.1. 什么是伪列

伪列是在ORACLE中的一个虚拟的列。

伪列的数据是由ORACLE进行维护和管理的,用户不能对这个列修改,只能查看。

所有的伪列要得到值必须要显式的指定。

最常用的两个伪列:rownum和rowid。

1.2. ROWNUM

ROWNUM(行号):是在查询操作时由ORACLE为每一行记录自动生成的一个编号。

每一次查询ROWNUM都会重新生成。(查询的结果中Oracle给你增加的一个编号,根据结果来重新生成)

rownum永远按照默认的顺序生成。(不受order by的影响)

rownum只能使用 <、 <= ,不能使用 > 、>= 符号,原因是:Oracle是基于行的数据库,行号永远是从1开始,即必须有第一行,才有第二行。

1.2.1. 行号的产生

  1. --需求:查询出所有员工信息,并且显示默认的行号列信息。
  2.  
  3. SELECT ROWNUM,t.* FROM emp t; -- * 和指定的列一起显示的时候,必须加别名

提示两点:

ROWNUM是由数据库自己产生的。ROWNUM查询的时候自动产生的。

1.2.2. 行号的排序

  1. --需求:查询出所有员工信息,按部门号正序排列,并且显示默认的行号列信息。
  2.  
  3. SELECT ROWNUM,t.* FROM emp t ORDER BY deptno;
  4.  
  5. --order by 原理:将查询结果(此时行号已经有了,已经和每一行数据绑定了)进行排序。
  6.  
  7. --order by 是查询语句出来的结果之后再排序的,rownu是在查询出来结果的时候产生。order by不会影响到行号
  8.  
  9. --先排序,再查询

  1. SELECT ROWNUM,t.* FROM
  2.  
  3. (
  4.  
  5. SELECT * FROM emp ORDER BY deptno
  6.  
  7. ) t

结论:

order by排序,不会影响到rownum的顺序。rownum永远按照默认的顺序生成。

所谓的“默认的顺序”,是指系统按照记录插入时的顺序(其实是rowid)。

1.2.3. 利用行号进行数据分页-重点

回顾mysql如何排序?

  1. select * from table limit m,n
  2. 其中m是指记录开始的index,从0开始,表示第一条记录
  3. n是指从第m+1条开始,取n条。
  4.  
  5. select * from tablename limit 3,3
  6. 即取出第4条至第6条,3条记录

Oracle如何分页呢?

结论:Mysql使用limit的关键字可以实现分页,但Oracle没有该关键字,无法使用该方法进行分页。

  1. SELECT ROWNUM,t.* FROM emp t; --查询所有记录
  2.  
  3. --需求:根据行号查询出第四条到第六条的员工信息。
  4. SELECT ROWNUM,t.* FROM emp t WHERE ROWNUM >=4 AND ROWNUM<=6;--错误
  5. -- rownum只能使用 < 、<=,不能使用 > 、>=符号,原因是:Oracle是基于行的数据库,行号永远是从1开始,即必须有第一行,才有第二行。
  6.  
  7. SELECT ROWNUM,t.* FROM emp t WHERE ROWNUM<=6; -- 查询1-6条记录
  8.  
  9. --方案:可以使用子查询(根据行号查询出第四条到第六条的员工信息)
  10. SELECT rownum,t2.* FROM
  11. (
  12. SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM<=6
  13. --此时子查询的rownum已经变成了虚表的一个列
  14. ) t2 --尽量让虚表尽量小
  15. WHERE t2.r >=4
  16.  
  1. Mysql分析:
  2. --需求:要分页查询,每页3条记录,查询第二页
  3. /*
  4. pageNum=2 当前页码
  5. pageSize=3 最大记录数(即每页显示几条记录)
  6.  
  7. 使用 mysql的分页查询语句,需要两个参数,起始索引和最大记录数
  8.  
  9. 计算:
  10. 起始索引:firstIndex=pageSize*(pageNum-1);
  11. 最大记录数:maxCount=pageSize;
  12.  
  13. 注意:
  14. 1.sql中索引是从1开始的
  15. 2.两个参数都是由当前页码和最大记录数计算出来的,所以使用时只定义页码和记录数即可
  16. 3.第一页的参数为(0,3),不是说记录的起始索引从0开始,这只是一个参数,实际效果是
  17. 从第1条记录开始,记录数为3条,即查询1,2,3三条记录
  18. 4.第二页的参数为(3,3),不是说记录的起始索引从3开始,这只是一个参数,实际效果是
  19. 从第4条记录开始,记录数为3条,即查询4,5,6三条记录,后面以此类推·····
  20.  
  21. Mysql语句:
  22. select * from 表名 limit 起始索引,最大记录数
  23. ------------------------------------------
  24.  
  25. Oracle分析:
  26. //起始行号
  27. firstRownum = pageSize*(pageNum-1)+1
  28. //结束行号
  29. endRownum = firstRownum+pageSize-1
  30.  
  31. 具体计算:
  32. firstRownum=3*(2-1)+1=4;
  33. endRownum=4+3-1=6;
  34. */
  35.  
  36. --写Oracle的分页,从子查询写起,也就是说从 <= 写起,或者说从endRownum写起
  37. SELECT ROWNUM ,t2.* FROM
  38. (
  39. SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6
  40. ) t2 WHERE t2.r >=4;
  41.  
  42. ------------------------------------------
  43.  
  44. --优化 --查询所有字段
  45. SELECT * FROM
  46. (
  47. SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6
  48. ) WHERE r >=4;
  49.  
  50. --优化 -- 结果指定字段
  51. SELECT empno,ename,job FROM
  52. (
  53. SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6
  54. ) WHERE r >=4;
  55.  
  56. ------------------------------------------
  57.  
  58. --需求:按照薪资的高低排序再分页
  59. SELECT * FROM
  60. (
  61. SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM <=6 ORDER BY sal DESC
  62. ) WHERE r >=4 ;
  1. --先排序薪资,再分页
  2. SELECT * FROM emp ORDER BY sal DESC;
  3. SELECT * FROM
  4. (
  5. SELECT ROWNUM r,t.* FROM
  6. (SELECT * FROM emp ORDER BY sal DESC) t
  7. WHERE ROWNUM <=6 ORDER BY sal DESC
  8. )
  9. WHERE r >=4 ;--Hibernate会自动将所有数据封装到实体对象(多余出来的行号那一列不会封装)
  10.  
  11. --如果不需要额外的字段,则只需要指定特定的列名就可以了。
  12. --优化:子查询字段尽量少一些。数据量少。比如,表中有100个字段,但你就想显示5个,那么,你就子查询中直接指定5个就ok了。但使用orm框架的建议都查出来。
  13. SELECT * FROM
  14. (
  15. SELECT ROWNUM r,t.* FROM
  16. (SELECT ename,job,sal FROM emp ORDER BY sal DESC) t
  17. WHERE ROWNUM <=6 ORDER BY sal DESC
  18. )
  19. WHERE r >=4 ;
  20.  
  21. --通用查询代码
  22. SELECT * FROM
  23. (
  24. SELECT ROWNUM r,t.* FROM
  25. (SELECT ename,job,sal FROM emp ORDER BY sal DESC) t
  26. WHERE ROWNUM <=endRownum ORDER BY sal DESC
  27. )
  28. WHERE r >=firstRownum ;
  29.  
  30. /*
  31. 另外一种计算方法(索引算法)
  32. firstIndex=pageSize*(pageNum-1);
  33. endRownum=firstIndex+pageSize;
  34. */
  35. SELECT * FROM
  36. (
  37. SELECT ROWNUM r,t.* FROM
  38. (SELECT ename,job,sal FROM emp ORDER BY sal DESC) t
  39. WHERE ROWNUM <=endRownum ORDER BY sal DESC
  40. )
  41. WHERE r > firstIndex;--Hibernate的内置算法

分析原因:

rownum只能使用<、 <=,不能使用>、 >=符号,原因是:Oracle是基于行的数据库,行号永远是从1开始,即必须有第一行,才有第二行。

【提示】:

如何记忆编写Oracle的分页?建议写的时候从里到外来写,即先写小于的条件的子查询(过滤掉rownum大于指定值的数据),再写大于的条件的查询(过滤掉rownum小于的值)。

Oracle的分页中如果需要排序显示,要先排序操作,再分页操作。(再嵌套一个子查询)

性能优化方面:建议在最里层的子查询中就直接指定字段或者其他的条件,减少数据的处理量。

1.3. ROWID

ROWID(记录编号):是表的伪列,是用来唯一标识表中的一条记录,并且间接给出了表行的物理位置,定位表行最快的方式。

主键:标识唯一的一条业务数据的标识。主键是给业务给用户用的。不是给数据库用的。

记录编号rowid:标识唯一的一条数据的。主要是给数据库用的。类似UUID。

1.3.1. ROWID的查看

SELECT t.*,ROWID FROM emp t;

注意:下面这种写法是错的

这两种写法可以:

1.3.2. ROWID的产生

使用insert语句插入数据时,oracle会自动生成rowid 并将其值与表数据一起存放到表行中。

这与rownum有很大不同,rownum不是表中原本的数据,只是在查询的时候才生成的。

提示:rownum默认的排序就是根据rowid

1.3.2. ROWID的作用

这里列举两个常见的应用:

去除重复数据。-- 在plsql Developer工具中,加上rowid可以更改数据。

关于主键和rowid的区别:

相同点:为了标识唯一一条记录的。

不同点:主键:针对业务数据,用来标识不同的一条业务数据。

      rowid:针对具体数据的,用来标识不同的唯一的一条数据,跟业务无关。

【示例】需求:删除表中的重复数据,要求保留重复记录中最早插入的那条。(DBA面试题)

  1. --查看rowid
  2. SELECT t.*,ROWID FROM emp t;
  3.  
  4. --需求:删除表中的重复数据,要求保留重复记录中最早插入的那条。(DBA面试题)
  5. --准备测试表和测试数据:
  6. --参考建表语句如下:
  7. -- Create table
  8. create table test
  9. (
  10. id number,
  11. name varchar2(50)
  12. );
  13.  
  14. --插入测试数据
  15. INSERT INTO TEST VALUES(1,'xiaoming');
  16. INSERT INTO TEST VALUES(2,'xiaoming');
  17. INSERT INTO TEST VALUES(3,'xiaoming');
  18. COMMIT;
  19. SELECT * FROM TEST ;
  20.  
  21. --通过rowid,剔除重复xiaoming,保留最早插入的xiaoming
  22. SELECT t.*,ROWID FROM TEST t;
  23.  
  24. --删除的的时候,可以先查询你要删除的东东
  25. SELECT t.*,ROWID FROM TEST t WHERE ROWID > (SELECT MIN(ROWID) FROM TEST);
  26. DELETE FROM TEST t WHERE ROWID > (SELECT MIN(ROWID) FROM TEST);
  27.  
  28. --语句有缺点:条件不足,会只保留一条数据,误删其他数据
  29. --重新插入测试数据
  30. INSERT INTO TEST VALUES(1,'xiaoming');
  31. INSERT INTO TEST VALUES(2,'xiaoming');
  32. INSERT INTO TEST VALUES(3,'xiaoming');
  33. INSERT INTO TEST VALUES(4,'Rose');
  34. INSERT INTO TEST VALUES(5,'Rose');
  35. COMMIT;
  36.  
  37. --剔除重复数据
  38. SELECT * FROM TEST WHERE ROWID NOT in(SELECT MIN(ROWID) FROM TEST GROUP BY NAME);
  39. DELETE TEST WHERE ROWID NOT in(SELECT MIN(ROWID) FROM TEST GROUP BY NAME);

注意:删除重复记录一定要小心,万一你的条件有问题,就会删错数据.建议删除之前,可以先用查询查一下,看是否是目标数据。

数据一旦删除恢复比较麻烦,但可以恢复,采用日志回滚。一般不要轻易用。

oracle04--伪列的更多相关文章

  1. oracle(sql)基础篇系列(三)——数据维护语句、数据定义语句、伪列

      DML语句 insert 向表中插入新的记录   --三种插入方式 --(1)不写字段的名字,直接按照字段的顺序把值逐个往里插 insert into dept2 values(50,'DANAM ...

  2. Oracle 中的伪列

    昨天做了一个Oracle PL/SQL 相关的测试,其中有一道这样的题目:   下列那些是Oracle的伪列(ACD)  A.ROWID   B.ROW_NUMBER()  C.LEVEL  D.RO ...

  3. SQL基础--ROWNUM伪列

    ROWNUM伪列 的概念: rownum表示的是一个数据行编号的伪列,它的内容是在用户查询数据时,为用户动态分配的一个数组(行号). 注意它是随机生成的,并不是和某一行数据绑定在一起的. 观察rown ...

  4. rownum和rowid伪列

    select row employee_id,last name,salary from employees; select row employee_id,last name,salary from ...

  5. ROWID伪列

    ROWID伪列概念: 在数据表中每一行所保存的记录,oracle会为每条记录分配一个唯一的地址编号,这个编号就是通过ROWID表示的. 所有的数据都利用ROWID进行定位. 观察rowid的存在 SQ ...

  6. Oracle分页查询=======之伪列的使用

    ========伪列========== 在Oracle数据库中,伪列不存在表中,但是可以从表中查询到 例如:SELECT ROWID 伪列,tname 教师姓名 FROM teacher; ==== ...

  7. oracle之rownum(伪列)

    整理和学习了一下网上高手关于rownum的帖子: 参考资料:  http://tech.ddvip.com/2008-10/122490439383296.html 和 http://tenn.jav ...

  8. Oracle中的伪列

    分页查询中,需要用到伪列rownum,代码如下: select * from (select rownum rn, name from cost where rownum <= 6) where ...

  9. 浅析SQL Server数据库中的伪列以及伪列的含义

    SQL Server中的伪列 下午看QQ群有人在讨论(非聚集)索引的存储,说,对于聚集索引表,非聚集索引存储的是索引键值+聚集索引键值:对于非聚集索引表,索引存储的是索引键值+RowId,这应该是一个 ...

  10. oracle伪列

    Oracle的伪列以及伪表 oracle系统为了实现完整的关系数据库功能,系统专门提供了一组成为伪列(Pseudocolumn)的数据库列,这些列不是在建立对象时由我们完成的,而是在我们建立时由Ora ...

随机推荐

  1. PHP中的PEAR是什么?

    PEAR也就是为PHP扩展与应用库(PHP Extension and Application Repository),它是一个PHP扩展及应用的一个代码仓库. 补充:php中扩展pecl与pear ...

  2. docker weave安装

    1.升级内核到3.10.0以上,安装iproute22.安装 0.80版本:#wget -O /usr/local/bin/weave https://raw.githubusercontent.co ...

  3. Windows Server 2008 R2 安装WinDbg以及符号路径设置

    1.下载WinDbg安装包(Debuggers And Tools-x64_en-us v6.12.0002.633 AMD64.msi),双击安装 2.从网站http://msdn.microsof ...

  4. Alpha,Beta,RC,RTM,EVAL,CTP,OEM,RTL,VOL

    微软的一个系统(如Win 7)或开发工具(VS系列),往往会对应很多种版本,下面就介绍一下这些版本的含义:   Alpha (阿尔法,希腊字母的第一位'α',代表最初的版本) Alpha是内部测试版, ...

  5. (转)enable_from_this方法的使用与陷阱

    转自http://blog.chinaunix.net/uid-442138-id-2122464.html   enable_from_this 的使用与实现原理说明:   shared_from_ ...

  6. 51nod 1293 球与切换器 | DP

    51nod 1293 球与切换器 | DP 题面 有N行M列的正方形盒子.每个盒子有三种状态0, -1, +1.球从盒子上边或左边进入盒子,从下边或右边离开盒子.规则: 如果盒子的模式是-1,则进入它 ...

  7. RRDtool绘制lvs连接数图形

    需求:用RRDtool绘制lvs的连接数图形 RRDtool是一个强大的绘图工具,作者是Tobias Oetiker. RRD全称Round Robin Database,轮转数据库,也是一个时间序列 ...

  8. 解题:USACO18FEB Taming the Herd

    题面 从零开始的DP学习系列之贰(我的DP真的就这么烂TAT) 设DP状态的另一个技巧,考虑题目中有关答案的各种信息 然后这种和结尾有关系的$dp$可以考虑向前找结尾来转移 设$dp[i][j]$表示 ...

  9. echarts分组柱状图的前后台处理 带平均线显示

    原生的echarts使用: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /&g ...

  10. sqlalchemy多外键关联

    一.前言 如果有张表A的多个字段关联另一张表B的一个字段,就如同一个客户表的账单地址和发货地址,同时关联地址表中的id字段. 二.事例 # -*- coding: UTF-8 -*- from sql ...