目录
数据伪列
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,job
2 from emp;
ROWNUM EMPNO ENAME JOB
---------- ---------- -------------------- ------------------
1 7369 SMITH CLERK
2 7499 ALLEN SALESMAN
3 7521 WARD SALESMAN
4 7566 JONES MANAGER
5 7654 MARTIN SALESMAN
6 7698 BLAKE MANAGER
7 7782 CLARK MANAGER
8 7839 KING PRESIDENT
9 7844 TURNER SALESMAN
10 7900 JAMES CLERK
11 7902 FORD ANALYST
际上数据表 emp 并没有 rownum这个列,但是仍然显示出 rownum,它是一个伪列,只是使用它生成行号
另一方面,可以发现 rownum在每一行显示的时候都会自动增加一个行号,
但需要记住的是,rownum生成的行号不是固定的,而是动态计算得来的
SQL> select rownum,empno,ename,job
2 from emp
3 where deptno=10;
ROWNUM EMPNO ENAME JOB
---------- ---------- -------------------- ------------------
1 7782 CLARK MANAGER
2 7839 KING PRESIDENT
3 7934 MILLER CLERK
此时,行号是根据查询结果动态计算出来的,所以每一个行号都不会与特定的记录捆绑
在实际的开发过程之中,rownum可以做两件事情
取得第一行数据
取得前 N 行数据
查询 emp 表中的记录并且取得第一行数据
SQL> select rownum,empno,ename,job
2 from emp
3 where deptno=10 and rownum=1;
ROWNUM EMPNO ENAME JOB
---------- ---------- -------------------- ------------------
1 7782 CLARK MANAGER
rownum此时只能查询第一行的数据,如果把上面查询语句中“rownum=1”修改为“rownum=2”,则无法查询数据
取得 emp 表的前 5 行记录
SQL> select rownum,empno,ename
2 from emp
3 where rownum<=5;
ROWNUM EMPNO ENAME
---------- ---------- --------------------
1 7369 SMITH
2 7499 ALLEN
3 7521 WARD
4 7566 JONES
5 7654 MARTIN
rowid
行 ID :rowid
rowid大部分情况下是在一些分析上使用的,而且在实际的开发过程中你也不会感受到 rowid存在
所谓的 rowid指的是每行数据提供的物理地址
SQL> select rowid,deptno,dname,loc
2 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 YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
10 ACCOUNTING NEW YORK
10 ACCOUNTING NEW YORK
30 SALES CHICAGO
20 RESEARCH DALLAS
已选择 8 行。
现在的问题是表中的数据列的信息几乎都是一样的,所以如果按照已有的字段删除,那么最终的结果是都会被删除掉
即便数据重复了,在 Oracle 里面存在一个 rowid,它的物理保存地址也是不可能重复的
SQL> select rowid,deptno,dname,loc
2 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 mydept
3 group by deptno,dname,loc;
DEPTNO DNAME LOC MIN(ROWID)
---------- ---------------------------- -------------------------- ------------------
20 RESEARCH DALLAS AAAT6wAAHAAAAGLAAB
10 ACCOUNTING NEW YORK AAAT6wAAHAAAAGLAAA
30 SALES CHICAGO AAAT6wAAHAAAAGLAAC
40 OPERATIONS BOSTON AAAT6wAAHAAAAGLAAD
可以看到每组中最小的 rowid
查询返回了所有需要保留的数据,那么所有不需要保留的数据就可以删除了
SQL> delete from mydept where rowid not in(
2 select min(rowid)
3 from mydept
4 group by deptno,dname,loc);
不过这样的操作只是一个使用说明,在以后讲解索引的时候会讲到 rowid 更多的使用情况