在對數據庫進行操作過程中我們可能會遇到這種情況,表中的數據可能重復出現,使我們對數據庫的操作過程中帶來 讀諸 多不便,那么怎么刪除這些重復沒有用的數據呢 ?
平時工作中可能會遇到當試圖對庫表中的某一列或幾列創建唯一索引時,系統提示 ORA-01452 :不能創建唯一索引,發現重復記錄。
重復的數據可能有這樣兩種情況 : 第一種 是 表中只有某些字段一樣,第二種是兩行記錄完全一樣 。刪除重復記錄后的結果也分為 2 種, 第一種 是重復的記錄全部刪除 ,第二種是 重復的記錄中只保留最新的一條記錄,一般業務中第二種的情況較多。
(1) 在Oracle 中,每一條記錄都有一個rowid ,rowid 在整個數據庫中是唯一的,rowid 確定了每條記錄是在Oracle 中的哪一個數據文件、塊、行上。
(2) 在重復的記錄中,可能所有列的內容都相同,但rowid 不會相同,所以只要確定出重復記錄中那些具有最大rowid 的就可以了,其余全部刪除。
想要刪除 部分 字段 重復的數據,可以使用下面語句進行刪除 ,下面的語句是刪除 表中字段1 和字段2 重復的數據 :
DELETE FROM 表名 a
WHERE ( 字段1 , 字段2 )
IN ( SELECT 字段1 , 字段2
FROM 表名
GROUP BY 字段1 ,
字段2
HAVING COUNT ( 1 ) > 1 )
;
上面的語句非常簡單,就是將查詢到的數據刪除掉。不過這種刪除執行的效率非常低,對于大數據量來說,可能會將數據庫吊死。所以建議先將查詢到的重復的數據插入到一個臨時表中,然后進行刪除,這樣,執行刪除的時候就不用再進行一次查詢了。如下:
CREATE TABLE 臨時表 AS ( select 字段1 , 字段2 , count (*) from 表名 group by 字段1 , 字段2 having count (*) > 1 ) ;
上面這句話就是建立了臨時表,并將查詢到的數據插入其中。下面就可以進行這樣的刪除操作了:
delete from 表名 a where 字段1 , 字段2 in ( select 字段1,字段2 from 臨時表 );
這種先建臨時表再進行刪除的操作要比直接用一條語句進行刪除要高效得多。
例子:
DELETE FROM tmp_lhr t
WHERE ( t.accesscode , t.lastserviceordercode , t.serviceinstancecode ) IN
( SELECT a.accesscode , a.lastserviceordercode , a.serviceinstancecode
FROM tmp_lhr a
GROUP BY a.accesscode ,
a.lastserviceordercode ,
a.serviceinstancecode
HAVING COUNT ( 1 ) > 1 );
假如 想保留重復數據中最新的一條記錄啊! 那怎么辦呢? 在oracle 中,有個隱藏了自動rowid ,里面給每條記錄一個唯一的rowid ,我們如果想保留最新的一條記錄,我們就可以利用這個字段,保留重復數據中r o wid 最大的一條記錄就可以了。
一、 如何查找重復記錄?
SELECT *
FROM TABLE_NAME A
WHERE ROWID NOT IN ( SELECT MAX ( ROWID )
FROM TABLE_NAME D
WHERE A .COL1 = D.COL1
AND A .COL2 = D.COL2 );
二、 如何刪除重復記錄? 1、 方法1
DELETE FROM TABLE_NAME
WHERE ROWID NOT IN ( SELECT MAX ( ROWID )
FROM TABLE_NAME D
group by d.col1 , d.col2 );
這種方法最簡單?。?!
2、 方法2
DELETE FROM TABLE_NAME A
WHERE ROWID NOT IN ( SELECT MAX ( ROWID )
FROM TABLE_NAME D
WHERE A .COL1 = D.COL1
AND A .COL2 = D.COL2 );
3、 方法3 臨時表
由此,我們要刪除重復數據,只保留最新的一條數據,就可以這樣寫了:
create table 臨時表 as select a.字段1 , a.字段2 , MAX ( a.ROWID ) dataid from 正式表 a GROUP BY a.字段1 , a.字段2 ;
DELETE FROM 正式 表 a
where a.rowid NOT IN ( SELECT b.dataid
FROM 臨時表 b
WHERE a.字段1 = b.字段1
and a.字段2 = b.字段2 );
commit ;
例子:
DELETE FROM tmp_lhr t
WHERE t.rowid not in ( SELECT MAX ( ROWID )
FROM tmp_lhr a
GROUP BY a.accesscode ,
a.lastserviceordercode ,
a.serviceinstancecode );
DELETE FROM tmp_lhr t
WHERE t.rowid !=
( SELECT MAX ( ROWID )
FROM tmp_lhr a
WHERE a.accesscode = t.accesscode
AND a.lastserviceordercode = t.lastserviceordercode
AND a.serviceinstancecode = t.serviceinstancecode );
----任意保留一條記錄
DELETE FROM ods_entity_info_full_lhr_01 T
WHERE T.ROWID NOT IN ( SELECT MAX ( A.ROWID )
FROM ods_entity_info_full_lhr_01 A
GROUP BY entity_code ,
entity_type );
---保留 entity_id 最大的一條記錄
DELETE FROM ods_entity_info_full_lhr_01 a
WHERE a.rowid NOT IN
( SELECT t.rowid
FROM ods_entity_info_full_lhr_01 t
WHERE ( t.entity_code , t.entity_type , t.entity_id ) IN
( SELECT entity_code ,
entity_type ,
MAX ( entity_id )
FROM ods_entity_info_full_lhr_01
GROUP BY entity_code ,
entity_type ));
對于表中兩行記錄完全一樣的情況,可以用下面 三種方式 獲取到去掉重復數據后的記錄:
1. select distinct * from 表名 ;
2. select * from 表名 group by 列名 1, 列名 2,... having count(*)>1
3. select * from 表名 a where rowid<(select max(rowid) from 表名 b where a. 列名 1=b. 列名 2 and ...)
DELETE FROM tmp_lhr t
WHERE t.rowid not in ( SELECT MAX ( ROWID )
FROM tmp_lhr a
GROUP BY a.accesscode ,
a.lastserviceordercode ,
a.serviceinstancecode );
可以將查詢的記錄放到臨時表中,然后再將原來的表記錄刪除,最后將臨時表的數據導回原來的表中。如下:
CREATE TABLE 臨時表 AS ( select distinct * from 表名 );
truncate table 正式表 ;
insert into 正式表 ( select * from 臨時表 );
drop table 臨時表 ;
DELETE FROM xr_maintainsite E
WHERE E.ROWID > ( SELECT MIN ( X.ROWID )
FROM xr_maintainsite X
WHERE X.Maintainid = E.Maintainid
AND x.siteid = e.siteid ); -- 這里被更新表中所有字段都需要寫全
給出一個例子:
delete from aa where rowid in(select rid from(select rowid rid,row_number() over (partition by name order by id) as seq from aa) where seq>1);
3 測試案例
SYS@raclhr1> CREATE TABLE T_ROWS_LHR_20160809 AS SELECT * FROM SCOTT.EMP;
Table created.
SYS@raclhr1> INSERT INTO T_ROWS_LHR_20160809 SELECT * FROM T_ROWS_LHR_20160809;
14 rows created.
SYS@raclhr1> COMMIT;
Commit complete.
SYS@raclhr1> INSERT INTO T_ROWS_LHR_20160809 SELECT * FROM T_ROWS_LHR_20160809;
28 rows created.
SYS@raclhr1> COMMIT;
Commit complete.
SYS@raclhr1> SELECT COUNT(1) FROM T_ROWS_LHR_20160809;
COUNT(1)
----------
56
SYS@raclhr1> DELETE FROM T_ROWS_LHR_20160809
2 WHERE ROWID NOT IN (SELECT MAX(ROWID)
3 FROM T_ROWS_LHR_20160809 D
4 group by D.EMPNO,D.ENAME,D.JOB,D.MGR,D.DEPTNO);
42 rows deleted.
SYS@raclhr1> SELECT COUNT(1) FROM T_ROWS_LHR_20160809;
COUNT(1)
----------
14
SYS@raclhr1> COMMIT;
Commit complete.
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。