暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

查查“身份证”,去掉冒名顶替

InDataBase 2021-06-30
621


Oracle数据库的表中的每一行数据都有一个唯一的标识符,或者称为rowid,在Oracle内部通常就是使用它来访问数据的。


rowid需要 10个字节的存储空间,并用18个字符来显示。该值表明了该行在Oracle数据库中的物理具体位置。可以在一个查询中使用rowid来表明查询结果中包含该值。


Oracle的物理扩展rowid有18位,每位采用64位编码,分别用A~Z、a~z、0~9、+、/共64个字符表示。


例如:


select rowid,empno from scott.emp;

ROWID EMPNO

------------------ ----------

AAAR3sAAEAAAACXAAA 7369

AAAR3sAAEAAAACXAAB 7499

AAAR3sAAEAAAACXAAC 7521

AAAR3sAAEAAAACXAAD 7566

AAAR3sAAEAAAACXAAE 7654

AAAR3sAAEAAAACXAAF 7698

AAAR3sAAEAAAACXAAG 7782

AAAR3sAAEAAAACXAAH 7788

AAAR3sAAEAAAACXAAI 7839

AAAR3sAAEAAAACXAAJ 7844

AAAR3sAAEAAAACXAAK 7876

AAAR3sAAEAAAACXAAL 7900

AAAR3sAAEAAAACXAAM 7902

AAAR3sAAEAAAACXAAN 7934

已选择14行。


这里的AAAR3s是数据库对象编号,AAE是文件标号,AAAACX是块编号,最后三位(empno = 7934时为AAN)是行编号。


 通过dbms_rowid包,可以直接得到具体的rowid包含的信息:


select 

dbms_rowid.rowid_object(rowid) object_id,

dbms_rowid.rowid_relative_fno(rowid) file_id,

dbms_rowid.rowid_block_number(rowid) block_id,

dbms_rowid.rowid_row_number(rowid) row_number 

from emp;


 OBJECT_ID    FILE_ID BLOCK_ID ROW_NUMBER

---------- ---------- ---------- ----------

     73196    4     151  0

     73196    4     151  1

     73196    4     151  2

     73196    4     151  3

     73196    4     151  4

     73196    4     151  5

     73196    4     151  6

     73196    4     151  7

     73196    4     151  8

     73196    4     151  9

     73196    4     151 10

     73196    4     151 11

     73196    4     151 12

     73196    4     151 13

已选择14行。



如何去掉重复记录?


一个表中上万条记录,由于没设置主键、唯一键,表中掺杂了一个相同的记录。

如何找到它们呢?如何删除掉它们呢?


表T(ID、NAME、AGE)

存在ID、NAME、AGE重复的记录。


如何查找表中多余的重复记录?

      这个SQL可以利用group by having 来处理

      select * from t

     where (id, name, age) in 

                (select id, name, age 

                   from t

                 group by id, name, age

                having count(*) > 1);


如何要删除这些重复的记录?

      这就需要用到rowid,rowid在数据库中可以唯一标识一条记录。删除时可保留最大的rowid或者最小的rowid所对应的记录即可。

      delete from t

      where (t.id, t.age, t.name) in

                 (select id, age, name 

                    from t 

                   group by id, age,name 

                  having count(*) >1)

          and rowid not in 

                     (select min(rowid) 

                       from t 

                     group by id, age,name 

                    having count(*) > 1);


      个人认为写成exists比较好理解:

      delete from t

      where exists 

                (select t1.rowid 

                  from t t1, 

                            (select id,age,name,min(rowid) rid 

                               from t 

                             group by id,age,name

                              having count(*) >1 ) b

                 where t1.id = b.id

                     and t1.age = b.age

                     and t1.name = b.name

                     and t1.rowid != b.rid

                     and t1.rowid = t.rowid);


文章转载自InDataBase,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论