目录
数据伪列
rownum
查询 emp 表中的记录并且取得第一行数据
取得 emp 表的前 5 行记录
rowid
面试题:表中有许多完全重复的数据,要求将重复的数据删除掉(只剩最早的一个)
Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645
数据伪列
之前学习过 sysdate伪列
所谓的伪列指的是列本身虽然不存在,但是却可以进行使用的列
在 Oracle 里面有两个非常重要的伪列:rownum、rowid
rownum
行号:rownum
如果在开发中使用了 rownum,那么就会自动生成行号
SQL> set linesize 250
SQL> select rownum,empno,ename,job2  from emp;ROWNUM      EMPNO ENAME                JOB
---------- ---------- -------------------- ------------------1       7369 SMITH                CLERK2       7499 ALLEN                SALESMAN3       7521 WARD                 SALESMAN4       7566 JONES                MANAGER5       7654 MARTIN               SALESMAN6       7698 BLAKE                MANAGER7       7782 CLARK                MANAGER8       7839 KING                 PRESIDENT9       7844 TURNER               SALESMAN10       7900 JAMES                CLERK11       7902 FORD                 ANALYST际上数据表 emp 并没有 rownum这个列,但是仍然显示出 rownum,它是一个伪列,只是使用它生成行号
另一方面,可以发现 rownum在每一行显示的时候都会自动增加一个行号,
但需要记住的是,rownum生成的行号不是固定的,而是动态计算得来的
SQL> select rownum,empno,ename,job2  from emp3  where deptno=10;ROWNUM      EMPNO ENAME                JOB
---------- ---------- -------------------- ------------------1       7782 CLARK                MANAGER2       7839 KING                 PRESIDENT3       7934 MILLER               CLERK此时,行号是根据查询结果动态计算出来的,所以每一个行号都不会与特定的记录捆绑
在实际的开发过程之中,rownum可以做两件事情
取得第一行数据
取得前 N 行数据
查询 emp 表中的记录并且取得第一行数据
SQL> select rownum,empno,ename,job2  from emp3  where deptno=10 and rownum=1;ROWNUM      EMPNO ENAME                JOB
---------- ---------- -------------------- ------------------1       7782 CLARK                MANAGERrownum此时只能查询第一行的数据,如果把上面查询语句中“rownum=1”修改为“rownum=2”,则无法查询数据
取得 emp 表的前 5 行记录
SQL> select rownum,empno,ename2  from emp3  where rownum<=5;ROWNUM      EMPNO ENAME
---------- ---------- --------------------1       7369 SMITH2       7499 ALLEN3       7521 WARD4       7566 JONES5       7654 MARTINrowid
行 ID :rowid
rowid大部分情况下是在一些分析上使用的,而且在实际的开发过程中你也不会感受到 rowid存在
所谓的 rowid指的是每行数据提供的物理地址
SQL> select rowid,deptno,dname,loc2  from dept;ROWID                  DEPTNO DNAME                        LOC
------------------ ---------- ---------------------------- --------------------------
AAAR29AAHAAAAFcAAA         10 ACCOUNTING                   NEW YORK
AAAR29AAHAAAAFcAAB         20 RESEARCH                     DALLAS
AAAR29AAHAAAAFcAAC         30 SALES                        CHICAGO
AAAR29AAHAAAAFcAAD         40 OPERATIONS                   BOSTON现在分析一下 rowid的组成,以“AAAR29AAHAAAAFcAAA”这个数据为例
数据对象编号:AAAR29
数据文件编号:AAH
数据保存的块号:AAAAFc
数据保存的行号:AAA
面试题:表中有许多完全重复的数据,要求将重复的数据删除掉(只剩最早的一个)
现在将 dept 表复制为 mydept
SQL> create table mydept as select * from dept;表已创建。有一张 mydept 表,由于疏于管理,导致表中出现了许多重复的内容,并且这些内容还是全都重复
INSERT INTO mydept(deptno,dname,loc) VALUES (10,'ACCOUNTING','NEW YORK') ;
INSERT INTO mydept(deptno,dname,loc) VALUES (10,'ACCOUNTING','NEW YORK') ;
INSERT INTO mydept(deptno,dname,loc) VALUES (30,'SALES','CHICAGO') ;
INSERT INTO mydept(deptno,dname,loc) VALUES (20,'RESEARCH','DALLAS') ;SQL> INSERT INTO mydept(deptno,dname,loc) VALUES (10,'ACCOUNTING','NEW YORK') ;已创建 1 行。SQL> INSERT INTO mydept(deptno,dname,loc) VALUES (10,'ACCOUNTING','NEW YORK') ;已创建 1 行。SQL> INSERT INTO mydept(deptno,dname,loc) VALUES (30,'SALES','CHICAGO') ;已创建 1 行。SQL> INSERT INTO mydept(deptno,dname,loc) VALUES (20,'RESEARCH','DALLAS') ;已创建 1 行。SQL> select *2  from mydept;DEPTNO DNAME                        LOC
---------- ---------------------------- --------------------------10 ACCOUNTING                   NEW YORK20 RESEARCH                     DALLAS30 SALES                        CHICAGO40 OPERATIONS                   BOSTON10 ACCOUNTING                   NEW YORK10 ACCOUNTING                   NEW YORK30 SALES                        CHICAGO20 RESEARCH                     DALLAS已选择 8 行。现在的问题是表中的数据列的信息几乎都是一样的,所以如果按照已有的字段删除,那么最终的结果是都会被删除掉
即便数据重复了,在 Oracle 里面存在一个 rowid,它的物理保存地址也是不可能重复的
SQL> select rowid,deptno,dname,loc2  from mydept;ROWID                  DEPTNO DNAME                        LOC
------------------ ---------- ---------------------------- --------------------------
AAAT6wAAHAAAAGLAAA         10 ACCOUNTING                   NEW YORK
AAAT6wAAHAAAAGLAAB         20 RESEARCH                     DALLAS
AAAT6wAAHAAAAGLAAC         30 SALES                        CHICAGO
AAAT6wAAHAAAAGLAAD         40 OPERATIONS                   BOSTON
AAAT6wAAHAAAAGPAAA         10 ACCOUNTING                   NEW YORK
AAAT6wAAHAAAAGPAAB         10 ACCOUNTING                   NEW YORK
AAAT6wAAHAAAAGPAAC         30 SALES                        CHICAGO
AAAT6wAAHAAAAGPAAD         20 RESEARCH                     DALLAS已选择 8 行。我们可以使用下面的代码删除其中重复的语句
SQL> delete from mydept where rowid='AAAT6wAAHAAAAGPAAA';已删除 1 行。只需替换上面代码中要删除的 rowid记录即可。最终清除完无用数据的结果
SQL> SELECT ROWID,deptno,dname,loc FROM mydept ;ROWID                  DEPTNO DNAME                        LOC
------------------ ---------- ---------------------------- --------------------------
AAAT6wAAHAAAAGLAAA         10 ACCOUNTING                   NEW YORK
AAAT6wAAHAAAAGLAAB         20 RESEARCH                     DALLAS
AAAT6wAAHAAAAGLAAC         30 SALES                        CHICAGO
AAAT6wAAHAAAAGLAAD         40 OPERATIONS                   BOSTON但是如果数据表中重复的数据太多,使用上面介绍的方法就不行了
此时,考虑到在程序中都会涉及累加的操作,所以理论上来说,最早保存数据的 rowid内容应该是最小的
如果要想确认最小,可以使用 min() 函数
现在 mydept 表中的数据有重复,那么可以采用分组,按照重复内容分组之后统计出最小的rowid(最早的 rowid)
SQL> select deptno,dname,loc,min(rowid)2  from mydept3  group by deptno,dname,loc;DEPTNO DNAME                        LOC                        MIN(ROWID)
---------- ---------------------------- -------------------------- ------------------20 RESEARCH                     DALLAS                     AAAT6wAAHAAAAGLAAB10 ACCOUNTING                   NEW YORK                   AAAT6wAAHAAAAGLAAA30 SALES                        CHICAGO                    AAAT6wAAHAAAAGLAAC40 OPERATIONS                   BOSTON                     AAAT6wAAHAAAAGLAAD可以看到每组中最小的 rowid
查询返回了所有需要保留的数据,那么所有不需要保留的数据就可以删除了
SQL> delete from mydept where rowid not in(2  select min(rowid)3  from mydept4  group by deptno,dname,loc);不过这样的操作只是一个使用说明,在以后讲解索引的时候会讲到 rowid 更多的使用情况
