欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

数据伪列

最编程 2024-03-07 17:17:34
...

目录

数据伪列

rownum

查询 emp 表中的记录并且取得第一行数据

取得 emp 表的前 5 行记录

 rowid

 面试题:表中有许多完全重复的数据,要求将重复的数据删除掉(只剩最早的一个)


Oracle从入门到总裁:https://blog.****.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 更多的使用情况